function maximum ( l, r : integer) -- inputs return integer is begin -- function max if l > r then return l; else return r; end if; end function maximum; function minimum ( l, r : integer) -- inputs return integer is begin -- function min if l > r then return r; else return l; end if; end function minimum; function "and" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) and r); end loop; return result; end function "and"; function "nand" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) nand r); end loop; return result; end function "nand"; function "or" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) or r); end loop; return result; end function "or"; function "nor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) nor r); end loop; return result; end function "nor"; function "xor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) xor r); end loop; return result; end function "xor"; function "xnor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is alias lv : BIT_VECTOR (1 to l'length) is l; variable result : BIT_VECTOR (1 to l'length); begin for i in result'range loop result(i) := (lv(i) xnor r); end loop; return result; end function "xnor"; function "and" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) and l); end loop; return result; end function "and"; function "nand" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) nand l); end loop; return result; end function "nand"; function "or" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) or l); end loop; return result; end function "or"; function "nor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) nor l); end loop; return result; end function "nor"; function "xor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) xor l); end loop; return result; end function "xor"; function "xnor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is alias rv : BIT_VECTOR (1 to r'length) is r; variable result : BIT_VECTOR (1 to r'length); begin for i in result'range loop result(i) := (rv(i) xnor l); end loop; return result; end function "xnor"; function and_reduce (arg : BIT_VECTOR) return BIT is variable Upper, Lower : bit; variable Half : integer; alias BUS_int : bit_vector (arg'length - 1 downto 0) is arg; variable Result : bit := '1'; -- In the case of a NULL range begin if (arg'LENGTH >= 1) then if (BUS_int'length = 1) then Result := BUS_int (BUS_int'left); elsif (BUS_int'length = 2) then Result := BUS_int(BUS_int'right) and BUS_int(BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := and_reduce (BUS_int (BUS_int'left downto Half)); Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper and Lower; end if; end if; return Result; end function and_reduce; ------------------------------------------------------------------- -- nand ------------------------------------------------------------------- function nand_reduce (arg : BIT_VECTOR) return BIT is begin return not and_reduce(arg); end function nand_reduce; ------------------------------------------------------------------- -- or ------------------------------------------------------------------- function or_reduce (arg : BIT_VECTOR) return BIT is variable Upper, Lower : bit; variable Half : integer; alias BUS_int : bit_vector (arg'length - 1 downto 0) is arg; variable Result : bit := '0'; -- In the case of a NULL range begin if (arg'LENGTH >= 1) then if (BUS_int'length = 1) then Result := BUS_int (BUS_int'left); elsif (BUS_int'length = 2) then Result := BUS_int(BUS_int'right) or BUS_int(BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := or_reduce (BUS_int (BUS_int'left downto Half)); Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper or Lower; end if; end if; return Result; end function or_reduce; ------------------------------------------------------------------- -- nor ------------------------------------------------------------------- function nor_reduce (arg : BIT_VECTOR) return BIT is begin return not or_reduce(arg); end function nor_reduce; ------------------------------------------------------------------- -- xor ------------------------------------------------------------------- function xor_reduce (arg : BIT_VECTOR) return BIT is variable Upper, Lower : bit; variable Half : integer; alias BUS_int : bit_vector (arg'length - 1 downto 0) is arg; variable Result : bit := '0'; -- In the case of a NULL range begin if (arg'LENGTH >= 1) then if (BUS_int'length = 1) then Result := BUS_int (BUS_int'left); elsif (BUS_int'length = 2) then Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper xor Lower; end if; end if; return Result; end function xor_reduce; ------------------------------------------------------------------- -- xnor ------------------------------------------------------------------- function xnor_reduce (arg : BIT_VECTOR) return BIT is begin return not xor_reduce(arg); end function xnor_reduce; constant NUS : STRING(2 to 1) := (others => ' '); -- NULL array constant NBSP : CHARACTER := CHARACTER'val(160); -- space character -- Hex Read and Write procedures for bit_vector. -- Procedure only visible internally. procedure Char2QuadBits (C : CHARACTER; RESULT : out BIT_VECTOR(3 downto 0); GOOD : out BOOLEAN; ISSUE_ERROR : in BOOLEAN) is begin case c is when '0' => result := x"0"; good := true; when '1' => result := x"1"; good := true; when '2' => result := x"2"; good := true; when '3' => result := x"3"; good := true; when '4' => result := x"4"; good := true; when '5' => result := x"5"; good := true; when '6' => result := x"6"; good := true; when '7' => result := x"7"; good := true; when '8' => result := x"8"; good := true; when '9' => result := x"9"; good := true; when 'A' | 'a' => result := x"A"; good := true; when 'B' | 'b' => result := x"B"; good := true; when 'C' | 'c' => result := x"C"; good := true; when 'D' | 'd' => result := x"D"; good := true; when 'E' | 'e' => result := x"E"; good := true; when 'F' | 'f' => result := x"F"; good := true; when others => assert not ISSUE_ERROR report "TEXTIO.HREAD Error: Read a '" & c & "', expected a Hex character (0-F)." severity error; GOOD := false; end case; end procedure Char2QuadBits; procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN) is variable ok : BOOLEAN; variable c : CHARACTER; constant ne : INTEGER := (VALUE'length+3)/4; constant pad : INTEGER := ne*4 - VALUE'length; variable sv : BIT_VECTOR (0 to ne*4 - 1) := (others => '0'); variable s : STRING(1 to ne-1); begin VALUE (VALUE'range) := (others => '0'); loop -- skip white space read(l, c, ok); exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; -- Bail out if there was a bad read if not ok then GOOD := false; return; end if; Char2QuadBits(c, sv(0 to 3), ok, false); if not ok then GOOD := false; return; end if; read(L, s, ok); if not ok then GOOD := false; return; end if; for i in 1 to ne-1 loop Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, false); if not ok then GOOD := false; return; end if; end loop; if or_reduce (sv (0 to pad-1)) = '1' then GOOD := false; -- vector was truncated. else GOOD := true; VALUE := sv (pad to sv'high); end if; end procedure HREAD; -- alias to_bstring is to_string [BIT_VECTOR, SIDE, WIDTH return STRING]; ------------------------------------------------------------------- -- TO_HSTRING ------------------------------------------------------------------- function to_hstring ( value : in BIT_VECTOR) return STRING is constant ne : INTEGER := (value'length+3)/4; constant pad : BIT_VECTOR(0 to (ne*4 - value'length) - 1) := (others => '0'); variable ivalue : BIT_VECTOR(0 to ne*4 - 1); variable result : STRING(1 to ne); variable quad : BIT_VECTOR(0 to 3); begin if value'length < 1 then return NUS; end if; ivalue := pad & value; for i in 0 to ne-1 loop quad := ivalue(4*i to 4*i+3); case quad is when x"0" => result(i+1) := '0'; when x"1" => result(i+1) := '1'; when x"2" => result(i+1) := '2'; when x"3" => result(i+1) := '3'; when x"4" => result(i+1) := '4'; when x"5" => result(i+1) := '5'; when x"6" => result(i+1) := '6'; when x"7" => result(i+1) := '7'; when x"8" => result(i+1) := '8'; when x"9" => result(i+1) := '9'; when x"A" => result(i+1) := 'A'; when x"B" => result(i+1) := 'B'; when x"C" => result(i+1) := 'C'; when x"D" => result(i+1) := 'D'; when x"E" => result(i+1) := 'E'; when x"F" => result(i+1) := 'F'; end case; end loop; return result; end function to_hstring; ------------------------------------------------------------------- -- TO_OSTRING ------------------------------------------------------------------- function to_ostring ( value : in BIT_VECTOR) return STRING is constant ne : INTEGER := (value'length+2)/3; constant pad : BIT_VECTOR(0 to (ne*3 - value'length) - 1) := (others => '0'); variable ivalue : BIT_VECTOR(0 to ne*3 - 1); variable result : STRING(1 to ne); variable tri : BIT_VECTOR(0 to 2); begin if value'length < 1 then return NUS; end if; ivalue := pad & value; for i in 0 to ne-1 loop tri := ivalue(3*i to 3*i+2); case tri is when o"0" => result(i+1) := '0'; when o"1" => result(i+1) := '1'; when o"2" => result(i+1) := '2'; when o"3" => result(i+1) := '3'; when o"4" => result(i+1) := '4'; when o"5" => result(i+1) := '5'; when o"6" => result(i+1) := '6'; when o"7" => result(i+1) := '7'; end case; end loop; return result; end function to_ostring; procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR) is variable ok : BOOLEAN; variable c : CHARACTER; constant ne : INTEGER := (VALUE'length+3)/4; constant pad : INTEGER := ne*4 - VALUE'length; variable sv : BIT_VECTOR(0 to ne*4 - 1) := (others => '0'); variable s : STRING(1 to ne-1); begin VALUE (VALUE'range) := (others => '0'); loop -- skip white space read(l, c, ok); exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; -- Bail out if there was a bad read if not ok then report "TEXTIO.HREAD Error: Failed skipping white space" severity error; return; end if; Char2QuadBits(c, sv(0 to 3), ok, true); if not ok then return; end if; read(L, s, ok); if not ok then report "TEXTIO.HREAD Error: Failed to read the STRING" severity error; return; end if; for i in 1 to ne-1 loop Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, true); if not ok then return; end if; end loop; if or_reduce (sv (0 to pad-1)) = '1' then report "TEXTIO.HREAD Error: Vector truncated" severity error; else VALUE := sv (pad to sv'high); end if; end procedure HREAD; procedure HWRITE (L : inout LINE; VALUE : in BIT_VECTOR; JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin write (L => L, VALUE => to_hstring(VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure HWRITE; -- Procedure only visible internally. procedure Char2TriBits (C : CHARACTER; RESULT : out BIT_VECTOR(2 downto 0); GOOD : out BOOLEAN; ISSUE_ERROR : in BOOLEAN) is begin case c is when '0' => result := o"0"; good := true; when '1' => result := o"1"; good := true; when '2' => result := o"2"; good := true; when '3' => result := o"3"; good := true; when '4' => result := o"4"; good := true; when '5' => result := o"5"; good := true; when '6' => result := o"6"; good := true; when '7' => result := o"7"; good := true; when others => assert not ISSUE_ERROR report "TEXTIO.OREAD Error: Read a '" & c & "', expected an Octal character (0-7)." severity error; GOOD := false; end case; end procedure Char2TriBits; -- Read and Write procedures for Octal values procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN) is variable ok : BOOLEAN; variable c : CHARACTER; constant ne : INTEGER := (VALUE'length+2)/3; constant pad : INTEGER := ne*3 - VALUE'length; variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); variable s : STRING(1 to ne-1); begin VALUE (VALUE'range) := (others => '0'); loop -- skip white space read(l, c, ok); exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; -- Bail out if there was a bad read if not ok then GOOD := false; return; end if; Char2TriBits(c, sv(0 to 2), ok, false); if not ok then GOOD := false; return; end if; read(L, s, ok); if not ok then GOOD := false; return; end if; for i in 1 to ne-1 loop Char2TriBits(s(i), sv(3*i to 3*i+2), ok, false); if not ok then GOOD := false; return; end if; end loop; if or_reduce (sv (0 to pad-1)) = '1' then GOOD := false; -- vector was truncated. else GOOD := true; VALUE := sv (pad to sv'high); end if; end procedure OREAD; procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR) is variable c : CHARACTER; variable ok : BOOLEAN; constant ne : INTEGER := (VALUE'length+2)/3; constant pad : INTEGER := ne*3 - VALUE'length; variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); variable s : STRING(1 to ne-1); begin VALUE (VALUE'range) := (others => '0'); loop -- skip white space read(l, c, ok); exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; -- Bail out if there was a bad read if not ok then report "TEXTIO.OREAD Error: Failed skipping white space" severity error; return; end if; Char2TriBits(c, sv(0 to 2), ok, true); if not ok then return; end if; read(L, s, ok); if not ok then report "TEXTIO.OREAD Error: Failed to read the STRING" severity error; return; end if; for i in 1 to ne-1 loop Char2TriBits(s(i), sv(3*i to 3*i+2), ok, true); if not ok then return; end if; end loop; if or_reduce (sv (0 to pad-1)) = '1' then report "TEXTIO.OREAD Error: Vector truncated" severity error; else VALUE := sv (pad to sv'high); end if; end procedure OREAD; procedure OWRITE (L : inout LINE; VALUE : in BIT_VECTOR; JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin write (L => L, VALUE => to_ostring(VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure OWRITE; -- Read and Write procedures for Binary values -- alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN]; -- alias BREAD is READ [LINE, BIT_VECTOR]; -- alias BWRITE is WRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; ----------------------------------------------------------------------------- -- to_string funcitons for bit_vector ----------------------------------------------------------------------------- function to_string ( value : in BIT_VECTOR ) return STRING is alias ivalue : BIT_VECTOR(1 to value'length) is value; variable result : STRING(1 to value'length); begin if value'length < 1 then return NUS; else for i in ivalue'range loop if iValue(i) = '0' then result(i) := '0'; else result(i) := '1'; end if; end loop; return result; end if; end function to_string; function to_string (value : UNSIGNED) return STRING is begin return to_string (BIT_VECTOR (value)); end function to_string; function to_string (value : SIGNED) return STRING is begin return to_string (BIT_VECTOR (value)); end function to_string;