langs a-z

This commit is contained in:
Ingy döt Net 2013-04-10 22:43:41 -07:00
parent db842d013d
commit d066446780
11389 changed files with 98361 additions and 1020 deletions

View file

@ -0,0 +1,202 @@
(* File blocks.ml
A block is just a black box with nin input lines and nout output lines,
numbered from 0 to nin-1 and 0 to nout-1 respectively. It will be stored
in a caml record, with the operation stored as a function. A value on
a line is represented by a boolean value. *)
type block = { nin:int; nout:int; apply:bool array -> bool array };;
(* First we need function for boolean conversion to and from integer values,
mainly for pretty printing of results *)
let int_of_bits nbits v =
if (Array.length v) <> nbits then failwith "bad args"
else
(let r = ref 0L in
for i=nbits-1 downto 0 do
r := Int64.add (Int64.shift_left !r 1) (if v.(i) then 1L else 0L)
done;
!r);;
let bits_of_int nbits n =
let v = Array.make nbits false
and r = ref n in
for i=0 to nbits-1 do
v.(i) <- (Int64.logand !r 1L) <> Int64.zero;
r := Int64.shift_right_logical !r 1
done;
v;;
let input nbits v =
let n = Array.length v in
let w = Array.make (n*nbits) false in
Array.iteri (fun i x ->
Array.blit (bits_of_int nbits x) 0 w (i*nbits) nbits
) v;
w;;
let output nbits v =
let nv = Array.length v in
let r = nv mod nbits and n = nv/nbits in
if r <> 0 then failwith "bad output size" else
Array.init n (fun i ->
int_of_bits nbits (Array.sub v (i*nbits) nbits)
);;
(* We have a type for blocks, so we need operations on blocks.
assoc: make one block from two blocks, side by side (they are not connected)
serial: connect input from one block to output of another block
parallel: make two outputs from one input passing through two blocks
block_array: an array of blocks linked by the same connector (assoc, serial, parallel) *)
let assoc a b =
{ nin=a.nin+b.nin; nout=a.nout+b.nout; apply=function
bits -> Array.append
(a.apply (Array.sub bits 0 a.nin))
(b.apply (Array.sub bits a.nin b.nin)) };;
let serial a b =
if a.nout <> b.nin then
failwith "[serial] bad block"
else
{ nin=a.nin; nout=b.nout; apply=function
bits -> b.apply (a.apply bits) };;
let parallel a b =
if a.nin <> b.nin then
failwith "[parallel] bad blocks"
else { nin=a.nin; nout=a.nout+b.nout; apply=function
bits -> Array.append (a.apply bits) (b.apply bits) };;
let block_array comb v =
let n = Array.length v
and r = ref v.(0) in
for i=1 to n-1 do
r := comb !r v.(i)
done;
!r;;
(* wires
map: map n input lines on length(v) output lines, using the links out(k)=v(in(k))
pass: n wires not connected (out(k) = in(k))
fork: a wire is developed into n wires having the same value
perm: permutation of wires
forget: n wires going nowhere
sub: subset of wires, other ones going nowhere *)
let map n v = { nin=n; nout=Array.length v; apply=function
bits -> Array.map (function k -> bits.(k)) v };;
let pass n = { nin=n; nout=n; apply=function
bits -> bits };;
let fork n = { nin=1; nout=n; apply=function
bits -> Array.make n bits.(0) };;
let perm v =
let n = Array.length v in
{ nin=n; nout=n; apply=function
bits -> Array.init n (function k -> bits.(v.(k))) };;
let forget n = { nin=n; nout=0; apply=function
bits -> [| |] };;
let sub nin nout where = { nin=nin; nout=nout; apply=function
bits -> Array.sub bits where nout };;
let transpose n p v =
if n*p <> Array.length v
then failwith "bad dim"
else
let w = Array.copy v in
for i=0 to n-1 do
for j=0 to p-1 do
let r = i*p+j and s = j*n+i in
w.(r) <- v.(s)
done
done;
w;;
(* line mixing (a special permutation)
mix 4 2 : 0,1,2,3, 4,5,6,7 -> 0,4, 1,5, 2,6, 3,7
unmix: inverse operation *)
let mix n p = perm (transpose n p (Array.init (n*p) (function x -> x)));;
let unmix n p = perm (transpose p n (Array.init (n*p) (function x -> x)));;
(* basic blocks
dummy: no input, no output, usually not useful
const: n wires with constant value (true or false)
encode: translates an Int64 into boolean values, keeping only n lower bits
bnand: NAND gate, the basic building block for all the other basic gates (or, and, not...) *)
let dummy = { nin=0; nout=0; apply=function
bits -> bits };;
let const b n = { nin=0; nout=n; apply=function
bits -> Array.make n b };;
let encode nbits x = { nin=0; nout=nbits; apply=function
bits -> bits_of_int nbits x };;
let bnand = { nin=2; nout=1; apply=function
[| a; b |] -> [| not (a && b) |] | _ -> failwith "bad args" };;
(* block evaluation : returns the value of the output, given an input and a block. *)
let eval block nbits_in nbits_out v =
output nbits_out (block.apply (input nbits_in v));;
(* building a 4-bit adder *)
(* first we build the usual gates *)
let bnot = serial (fork 2) bnand;;
let band = serial bnand bnot;;
(* a or b = !a nand !b *)
let bor = serial (assoc bnot bnot) bnand;;
(* line "a" -> two lines, "a" and "not a" *)
let a_not_a = parallel (pass 1) bnot;;
let bxor = block_array serial [|
assoc a_not_a a_not_a;
perm [| 0; 3; 1; 2 |];
assoc band band;
bor |];;
let half_adder = parallel bxor band;;
(* bits C0,A,B -> S,C1 *)
let full_adder = block_array serial [|
assoc half_adder (pass 1);
perm [| 1; 0; 2 |];
assoc (pass 1) half_adder;
perm [| 1; 0; 2 |];
assoc (pass 1) bor |];;
(* 4-bit adder *)
let add4 = block_array serial [|
mix 4 2;
assoc half_adder (pass 6);
assoc (assoc (pass 1) full_adder) (pass 4);
assoc (assoc (pass 2) full_adder) (pass 2);
assoc (pass 3) full_adder |];;
(* 4-bit adder and three supplementary lines to make a multiple of 4 (to translate back to 4-bit integers) *)
let add4_io = assoc add4 (const false 3);;
(* wrapping the 4-bit to input and output integers instead of booleans
plus a b -> (sum,carry)
*)
let plus a b =
let v = Array.map Int64.to_int
(eval add4_io 4 4 (Array.map Int64.of_int [| a; b |])) in
v.(0), v.(1);;

View file

@ -0,0 +1,13 @@
# open Blocks;;
# plus 4 5;;
- : int * int = (9, 0)
# plus 15 1;;
- : int * int = (0, 1)
# plus 15 15;;
- : int * int = (14, 1)
# plus 0 0;;
- : int * int = (0, 0)

View file

@ -0,0 +1,14 @@
(* general adder (n bits with n <= 64) *)
let gen_adder n = block_array serial [|
mix n 2;
assoc half_adder (pass (2*n-2));
block_array serial (Array.init (n-2) (function k ->
assoc (assoc (pass (k+1)) full_adder) (pass (2*(n-k-2)))));
assoc (pass (n-1)) full_adder |];;
let gadd_io n = assoc (gen_adder n) (const false (n-1));;
let gen_plus n a b =
let v = Array.map Int64.to_int
(eval (gadd_io n) n n (Array.map Int64.of_int [| a; b |])) in
v.(0), v.(1);;

View file

@ -0,0 +1,4 @@
# gen_plus 7 100 100;;
- : int * int = (72, 1)
# gen_plus 8 100 100;;
- : int * int = (200, 0)

View file

@ -0,0 +1,12 @@
xor(a,b)=(!a&b)|(a&!b);
halfadd(a,b)=[a&b,xor(a,b)];
fulladd(a,b,c)=my(t=halfadd(a,c),s=halfadd(t[2],b));[t[1]|s[1],s[2]];
add4(a3,a2,a1,a0,b3,b2,b1,b0)={
my(s0,s1,s2,s3);
s0=fulladd(a0,b0,0);
s1=fulladd(a1,b1,s0[1]);
s2=fulladd(a2,b2,s1[1]);
s3=fulladd(a3,b3,s2[1]);
[s3[1],s3[2],s2[2],s1[2],s0[2]]
};
add4(0,0,0,0,0,0,0,0)

View file

@ -0,0 +1,35 @@
/* 4-BIT ADDER */
TEST: PROCEDURE OPTIONS (MAIN);
DECLARE CARRY_IN BIT (1) STATIC INITIAL ('0'B) ALIGNED;
declare (m, n, sum)(4) bit(1) aligned;
declare i fixed binary;
get edit (m, n) (b(1));
put edit (m, ' + ', n, ' = ') (4 b, a);
do i = 4 to 1 by -1;
call full_adder ((carry_in), m(i), n(i), sum(i), carry_in);
end;
put edit (sum) (b);
HALF_ADDER: PROCEDURE (IN1, IN2, SUM, CARRY);
DECLARE (IN1, IN2, SUM, CARRY) BIT (1) ALIGNED;
SUM = ( ^IN1 & IN2) | ( IN1 & ^IN2);
/* Exclusive OR using only AND, NOT, OR. */
CARRY = IN1 & IN2;
END HALF_ADDER;
FULL_ADDER: PROCEDURE (CARRY_IN, IN1, IN2, SUM, CARRY);
DECLARE (CARRY_IN, IN1, IN2, SUM, CARRY) BIT (1) ALIGNED;
DECLARE (SUM2, CARRY2) BIT (1) ALIGNED;
CALL HALF_ADDER (CARRY_IN, IN1, SUM, CARRY);
CALL HALF_ADDER (SUM, IN2, SUM2, CARRY2);
SUM = SUM2;
CARRY = CARRY | CARRY2;
END FULL_ADDER;
END TEST;

View file

@ -0,0 +1,28 @@
sub xor ($a, $b) { ($a and not $b) or (not $a and $b) }
sub half-adder ($a, $b) {
return xor($a, $b), ($a and $b);
}
sub full-adder ($a, $b, $c0) {
my ($ha0_s, $ha0_c) = half-adder($c0, $a);
my ($ha1_s, $ha1_c) = half-adder($ha0_s, $b);
return $ha1_s, ($ha0_c or $ha1_c);
}
sub four-bit-adder ($a0, $a1, $a2, $a3, $b0, $b1, $b2, $b3) {
my ($fa0_s, $fa0_c) = full-adder($a0, $b0, 0);
my ($fa1_s, $fa1_c) = full-adder($a1, $b1, $fa0_c);
my ($fa2_s, $fa2_c) = full-adder($a2, $b2, $fa1_c);
my ($fa3_s, $fa3_c) = full-adder($a3, $b3, $fa2_c);
return $fa0_s, $fa1_s, $fa2_s, $fa3_s, $fa3_c;
}
{
use Test;
is four-bit-adder(1, 0, 0, 0, 1, 0, 0, 0), (0, 1, 0, 0, 0), '1 + 1 == 2';
is four-bit-adder(1, 0, 1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0), '5 + 5 == 10';
is four-bit-adder(1, 0, 0, 1, 1, 1, 1, 0)[4], 1, '7 + 9 == overflow';
}

View file

@ -0,0 +1,52 @@
function bxor2 ( [byte] $a, [byte] $b )
{
$out1 = $a -band ( -bnot $b )
$out2 = ( -bnot $a ) -band $b
$out1 -bor $out2
}
function hadder ( [byte] $a, [byte] $b )
{
@{
"S"=bxor2 $a $b
"C"=$a -band $b
}
}
function fadder ( [byte] $a, [byte] $b, [byte] $cd )
{
$out1 = hadder $cd $a
$out2 = hadder $out1["S"] $b
@{
"S"=$out2["S"]
"C"=$out1["C"] -bor $out2["C"]
}
}
function FourBitAdder ( [byte] $a, [byte] $b )
{
$a0 = $a -band 1
$a1 = ($a -band 2)/2
$a2 = ($a -band 4)/4
$a3 = ($a -band 8)/8
$b0 = $b -band 1
$b1 = ($b -band 2)/2
$b2 = ($b -band 4)/4
$b3 = ($b -band 8)/8
$out1 = fadder $a0 $b0 0
$out2 = fadder $a1 $b1 $out1["C"]
$out3 = fadder $a2 $b2 $out2["C"]
$out4 = fadder $a3 $b3 $out3["C"]
@{
"S"="{3}{2}{1}{0}" -f $out1["S"], $out2["S"], $out3["S"], $out4["S"]
"V"=$out4["C"]
}
}
FourBitAdder 3 5
FourBitAdder 0xA 5
FourBitAdder 0xC 0xB
[Convert]::ToByte((FourBitAdder 0xC 0xB)["S"],2)

View file

@ -0,0 +1,54 @@
;Because no representation for a solitary bit is present, bits are stored as bytes.
;Output values from the constructive building blocks is done using pointers (i.e. '*').
Procedure.b notGate(x)
ProcedureReturn ~x
EndProcedure
Procedure.b xorGate(x,y)
ProcedureReturn (x & notGate(y)) | (notGate(x) & y)
EndProcedure
Procedure halfadder(a, b, *sum.Byte, *carry.Byte)
*sum\b = xorGate(a, b)
*carry\b = a & b
EndProcedure
Procedure fulladder(a, b, c0, *sum.Byte, *c1.Byte)
Protected sum_ac.b, carry_ac.b, carry_sb.b
halfadder(c0, a, @sum_ac, @carry_ac)
halfadder(sum_ac, b, *sum, @carry_sb)
*c1\b = carry_ac | carry_sb
EndProcedure
Procedure fourbitsadder(a0, a1, a2, a3, b0, b1, b2, b3 , *s0.Byte, *s1.Byte, *s2.Byte, *s3.Byte, *v.Byte)
Protected.b c1, c2, c3
fulladder(a0, b0, 0, *s0, @c1)
fulladder(a1, b1, c1, *s1, @c2)
fulladder(a2, b2, c2, *s2, @c3)
fulladder(a3, b3, c3, *s3, *v)
EndProcedure
;// Test implementation, map two 4-character strings to the inputs of the fourbitsadder() and display results
Procedure.s test_4_bit_adder(a.s,b.s)
Protected.b s0, s1, s2, s3, v, i
Dim a.b(3)
Dim b.b(3)
For i = 0 To 3
a(i) = Val(Mid(a, 4 - i, 1))
b(i) = Val(Mid(b, 4 - i, 1))
Next
fourbitsadder(a(0), a(1), a(2), a(3), b(0), b(1), b(2), b(3), @s0, @s1, @s2, @s3, @v)
ProcedureReturn a + " + " + b + " = " + Str(s3) + Str(s2) + Str(s1) + Str(s0) + " overflow " + Str(v)
EndProcedure
If OpenConsole()
PrintN(test_4_bit_adder("0110","1110"))
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf

View file

@ -0,0 +1,33 @@
module Half_Adder( input a, b, output s, c );
assign s = a ^ b;
assign c = a & b;
endmodule
module Full_Adder( input a, b, c_in, output s, c_out );
wire s_ha1, c_ha1, c_ha2;
Half_Adder ha1( .a(c_in), .b(a), .s(s_ha1), .c(c_ha1) );
Half_Adder ha2( .a(s_ha1), .b(b), .s(s), .c(c_ha2) );
assign c_out = c_ha1 | c_ha2;
endmodule
module Multibit_Adder(a,b,s);
parameter N = 8;
input [N-1:0] a;
input [N-1:0] b;
output [N:0] s;
wire [N:0] c;
assign c[0] = 0;
assign s[N] = c[N];
generate
genvar I;
for (I=0; I<N; ++I) Full_Adder add( .a(a[I]), .b(b[I]), .s(s[I]), .c_in(c[I]), .c_out(c[I+1]) );
endgenerate
endmodule

View file

@ -0,0 +1,30 @@
module simTop();
bit [3:0] a;
bit [3:0] b;
bit [4:0] s;
Multibit_Adder#(4) adder(.*);
always_comb begin
$display( "%d + %d = %d", a, b, s );
assert( s == a+b );
end
endmodule
program Main();
class Test;
rand bit [3:0] a;
rand bit [3:0] b;
endclass
Test t = new;
initial repeat (20) begin
#10 t.randomize;
simTop.a = t.a;
simTop.b = t.b;
end
endprogram

View file

@ -0,0 +1,29 @@
function XOR(%a, %b)
{
return (!%a && %b) || (%a && !%b);
}
//Seperated by space
function HalfAdd(%a, %b)
{
return XOR(%a, %b) SPC %a && %b;
}
//First word is the carry bit
function FullAdd(%a, %b, %c0)
{
%r1 = HalfAdd(%a, %c0);
%r2 = HalfAdd(getWord(%r1, 0), %b);
%r3 = getWord(%r1, 1) || getWord(%r2, 1);
return %r3 SPC getWord(%r2, 0);
}
//Outputs each bit seperated by a space.
function FourBitFullAdd(%a0, %a1, %a2, %a3, %b0, %b1, %b2, %b3)
{
%r0 = FullAdd(%a0, %b0, 0);
%r1 = FullAdd(%a1, %b1, getWord(%r0, 0));
%r2 = FullAdd(%a2, %b2, getWord(%r1, 0));
%r3 = FullAdd(%a3, %b3, getWord(%r2, 0));
return getWord(%r0,1) SPC getWord(%r1,1) SPC getWord(%r2,1) SPC getWord(%r3,1) SPC getWord(%r3,0);
}

View file

@ -0,0 +1,161 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity four_bit_adder is
port(
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector (3 downto 0);
s : out std_logic_vector (3 downto 0);
v : out std_logic
);
end four_bit_adder ;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity fa is
port(
a : in std_logic;
b : in std_logic;
ci : in std_logic;
co : out std_logic;
s : out std_logic
);
end fa ;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity ha is
port(
a : in std_logic;
b : in std_logic;
c : out std_logic;
s : out std_logic
);
end ha ;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity xor_gate is
port(
a : in std_logic;
b : in std_logic;
x : out std_logic
);
end xor_gate ;
architecture struct of four_bit_adder is
signal ci0 : std_logic;
signal co0 : std_logic;
signal co1 : std_logic;
signal co2 : std_logic;
component fa
port (
a : in std_logic ;
b : in std_logic ;
ci : in std_logic ;
co : out std_logic ;
s : out std_logic
);
end component;
begin
ci0 <= '0';
i_fa0 : fa
port map (
a => a(0),
b => b(0),
ci => ci0,
co => co0,
s => s(0)
);
i_fa1 : fa
port map (
a => a(1),
b => b(1),
ci => co0,
co => co1,
s => s(1)
);
i_fa2 : fa
port map (
a => a(2),
b => b(2),
ci => co1,
co => co2,
s => s(2)
);
i_fa3 : fa
port map (
a => a(3),
b => b(3),
ci => co2,
co => v,
s => s(3)
);
end struct;
architecture struct of fa is
signal c1 : std_logic;
signal c2 : std_logic;
signal s1 : std_logic;
component ha
port (
a : in std_logic ;
b : in std_logic ;
c : out std_logic ;
s : out std_logic
);
end component;
begin
co <= c1 or c2;
i_ha0 : ha
port map (
a => ci,
b => a,
c => c1,
s => s1
);
i_ha1 : ha
port map (
a => s1,
b => b,
c => c2,
s => s
);
end struct;
architecture struct of ha is
component xor_gate
port (
a : in std_logic;
b : in std_logic;
x : out std_logic
);
end component;
begin
c <= a and b;
i_xor_gate : xor_gate
port map (
a => a,
b => b,
x => s
);
end struct;
architecture rtl of xor_gate is
begin
x <= (a and not b) or (b and not a);
end architecture rtl;

View file

@ -0,0 +1,45 @@
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
entity tb is
end tb ;
architecture struct of tb is
signal a : std_logic_vector(3 downto 0);
signal b : std_logic_vector(3 downto 0);
signal s : std_logic_vector(3 downto 0);
signal v : std_logic;
component four_bit_adder
port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector (3 downto 0);
s : out std_logic_vector (3 downto 0);
v : out std_logic
);
end component;
begin
proc_test: process
begin
for x in 0 to 15 loop
for y in 0 to 15 loop
a <= std_logic_vector(to_unsigned(x, 4));
b <= std_logic_vector(to_unsigned(y, 4));
wait for 100 ns;
end loop;
end loop;
wait;
end process;
i_four_bit_adder : four_bit_adder
port map (
a => a,
b => b,
s => s,
v => v
);
end struct;

View file

@ -0,0 +1,59 @@
code CrLf=9, IntOut=11;
func Not(A);
int A;
return not A;
func And(A, B);
int A, B;
return A and B;
func Or(A, B);
int A, B;
return A or B;
func Xor(A, B);
int A, B;
return Or(And(A, Not(B)), And(Not(A), B));
proc HalfAdd(A, B, S, C);
int A, B, S, C;
[S(0):= Xor(A, B);
C(0):= And(A, B);
];
proc FullAdd(A, B, Ci, S, Co);
int A, B, Ci, S, Co; \(Ci and Co are reversed from drawing)
int S0, S1, C0, C1;
[HalfAdd(Ci, A, @S0, @C0);
HalfAdd(S0, B, @S1, @C1);
S(0):= S1;
Co(0):= Or(C0, C1);
];
proc Add4Bits(A0, A1, A2, A3, B0, B1, B2, B3, S0, S1, S2, S3, Co);
int A0, A1, A2, A3, B0, B1, B2, B3, S0, S1, S2, S3, Co;
int Co0, Co1, Co2;
[FullAdd(A0, B0, 0, S0, @Co0);
FullAdd(A1, B1, Co0, S1, @Co1);
FullAdd(A2, B2, Co1, S2, @Co2);
FullAdd(A3, B3, Co2, S3, Co);
];
proc BinOut(D, A0, A1, A2, A3, C);
int D, A0, A1, A2, A3, C;
[IntOut(D, C&1);
IntOut(D, A3&1);
IntOut(D, A2&1);
IntOut(D, A1&1);
IntOut(D, A0&1);
];
int S0, S1, S2, S3, C;
[Add4Bits(1, 0, 0, 0, 0, 0, 1, 0, @S0, @S1, @S2, @S3, @C); \0001 + 0100 = 00101
BinOut(0, S0, S1, S2, S3, C); CrLf(0);
Add4Bits(1, 0, 1, 0, 0, 1, 1, 1, @S0, @S1, @S2, @S3, @C); \0101 + 1110 = 10011
BinOut(0, S0, S1, S2, S3, C); CrLf(0);
Add4Bits(1, 1, 1, 1, 1, 1, 1, 1, @S0, @S1, @S2, @S3, @C); \1111 + 1111 = 11110
BinOut(0, S0, S1, S2, S3, C); CrLf(0);
]