OpenCores
URL https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk

Subversion Repositories tcp_socket

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /tcp_socket/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/source/HTTP_test.c
0,0 → 1,11
unsigned put_socket(int i){
file_write(i, "packet");
return 0;
}
 
#include "HTTP.h"
 
//simple echo application
void main(){
HTTP_GET_response("Hello!\n");
}
/source/print.h
0,0 → 1,108
////////////////////////////////////////////////////////////////////////////////
//
// CHIPS-2.0 print.h
//
// :Author: Jonathan P Dawson
// :Date: 22/10/2013
// :email: chips@jondawson.org.uk
// :license: MIT
// :Copyright: Copyright (C) Jonathan P Dawson 2013
//
// Print values to stdout. Before including this file,
// void stdout_put_char(unsigned i) must be defined.
//
// This task is left to the user so that stdout can be directed to uart/socket
// as required.
//
////////////////////////////////////////////////////////////////////////////////
 
 
//Print a string *string* to stdout
void print_string(unsigned string[]){
unsigned i=0;
while(string[i]){
stdout_put_char(string[i]);
i++;
}
}
 
//Print an unsigned int to stdout in hex format
void print_uhex(unsigned uhex){
unsigned digit_3 = (uhex >> 12) & 0xf;
unsigned digit_2 = (uhex >> 8) & 0xf;
unsigned digit_1 = (uhex >> 4) & 0xf;
unsigned digit_0 = uhex & 0xf;
if(digit_3 < 9) stdout_put_char(digit_3 | 0x30);
else stdout_put_char(digit_3 + 87);
if(digit_2 < 9) stdout_put_char(digit_2 | 0x30);
else stdout_put_char(digit_2 + 87);
if(digit_1 < 9) stdout_put_char(digit_1 | 0x30);
else stdout_put_char(digit_1 + 87);
if(digit_0 < 9) stdout_put_char(digit_0 | 0x30);
else stdout_put_char(digit_0 + 87);
}
 
//Print an unsigned int to stdout in decimal format
//leading 0s will be suppressed
void print_udecimal(unsigned udecimal){
unsigned digit;
unsigned significant = 0;
digit = 0;
while(udecimal >= 10000){
udecimal -= 10000;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 1000){
udecimal -= 1000;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 100){
udecimal -= 100;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 10){
udecimal -= 10;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
stdout_put_char(udecimal | 0x30);
}
 
//Print a signed int to stdout in hex format
void print_hex(int hex){
if(hex >= 0){
print_uhex(hex);
} else {
stdout_put_char('-');
print_uhex(-hex);
}
}
 
//Print a signed int to stdout in decimal format
//leading 0s will be suppressed
void print_decimal(int decimal){
if(decimal >= 0){
print_udecimal(decimal);
} else {
stdout_put_char('-');
print_udecimal(-decimal);
}
}
/source/gigabit_ethernet.vhd
0,0 → 1,660
--------------------------------------------------------------------------------
---
--- Gigabit Ethernet MAC
---
--- :Author: Jonathan P Dawson
--- :Date: 17/10/2013
--- :email: chips@jondawson.org.uk
--- :license: MIT
--- :Copyright: Copyright (C) Jonathan P Dawson 2013
---
--- A gigabit ethernet MAC
---
--------------------------------------------------------------------------------
---
---Gigabit Ethernet
---================
---
---Send and receive Ethernet packets. Using a Ethernet Physical Interface.
---
---Features:
---
---+ Supports 1Gbit/s ethernet only via a gmii interface.
---+ Supports full duplex mode only.
---
---Interface
------------
---:input: TX - Data to send (16 bits).
---:output: RX - Data to send (16 bits).
---
---Ethernet Packet Structure
----------------------------
---
---+-------------+-------------+--------+--------+---------+---------+-----+
---| Description | destination | source | length | payload | padding | FSC |
---+=============+=============+========+========+=========+=========+=====+
---| Bytes | 6 | 6 | 2 | 0-1500 | 0-46 | 4 |
---+-------------+-------------+--------+--------+---------+---------+-----+
---
---Notes:
---
---+ The *length* field is the length of the ethernet payload.
---+ The *Ethernet Output* block will automatically append the FSC to
--- outgoing packets.
---+ The *FSC* of incoming packets will be checked, and bad packets will
--- be discarded. The *FSC* will be stripped from incoming packets.
---+ The length of the *payload* + *padding* must be 46-1500 bytes.
---+ Incoming packets of incorrect *length* will be discarded.
---
---Usage
--------
---
---Transmit
---~~~~~~~~
---The first 16 bit word on the TX input is interpreted as the length of the
---packet in bytes (including the MAC address, length and payload, but not the
---preamble or FSC). Subsequent words on the TX input are interpreted as the
---content of the packet. If length is an odd number of bytes, then the least
---significant byte of the last word will be ignored.
---The FSC will be appended for you, but you need to supply the destination,
---source and length fields.
---
---Receive
---~~~~~~~~
---The first 16 bit word on the RX output will be the length of the packet in
---bytes (including the MAC address, length and payload, but not the
---preamble or FSC). Subsequent words on the RX output will be the
---content of the packet. If length is an odd number of bytes, then the least
---significant byte of the last word will not contain usefull data.
---The FSC will be stripped from incoming packets, but the destination,
---source and length fields will be included.
---
---Hardware details
-------------------
---This component used two clocks, the local clock used to transfer data
---between components, and a 125MHz clock source for sending data to the
---Ethernet physical interface. This clock is also forwarded along with the
---data to the ethernet phy.
---
 
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
 
entity gigabit_ethernet is
port(
CLK : in std_logic;
RST : in std_logic;
 
--Ethernet Clock
CLK_125_MHZ : in std_logic;
 
--GMII IF
GTXCLK : out std_logic;
TXCLK : in std_logic;
TXER : out std_logic;
TXEN : out std_logic;
TXD : out std_logic_vector(7 downto 0);
PHY_RESET : out std_logic;
RXCLK : in std_logic;
RXER : in std_logic;
RXDV : in std_logic;
RXD : in std_logic_vector(7 downto 0);
 
--RX STREAM
TX : in std_logic_vector(15 downto 0);
TX_STB : in std_logic;
TX_ACK : out std_logic;
 
--RX STREAM
RX : out std_logic_vector(15 downto 0);
RX_STB : out std_logic;
RX_ACK : in std_logic
);
end entity gigabit_ethernet;
 
architecture RTL of gigabit_ethernet is
 
-- polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
-- data width: 8
-- convention: the first serial bit is D[0]
function NEXTCRC32_D8
(DATA: std_logic_vector(7 downto 0);
CRC: std_logic_vector(31 downto 0))
return std_logic_vector is
 
variable D: std_logic_vector(7 downto 0);
variable C: std_logic_vector(31 downto 0);
variable NEWCRC: std_logic_vector(31 downto 0);
begin
D := DATA;
C := CRC;
NewCRC(0):=C(24) xor C(30) xor D(1) xor D(7);
NewCRC(1):=C(25) xor C(31) xor D(0) xor D(6) xor C(24) xor C(30) xor D(1)
xor D(7);
NewCRC(2):=C(26) xor D(5) xor C(25) xor C(31) xor D(0) xor D(6) xor C(24)
xor C(30) xor D(1) xor D(7);
NewCRC(3):=C(27) xor D(4) xor C(26) xor D(5) xor C(25) xor C(31) xor D(0)
xor D(6);
NewCRC(4):=C(28) xor D(3) xor C(27) xor D(4) xor C(26) xor D(5) xor C(24)
xor C(30) xor D(1) xor D(7);
NewCRC(5):=C(29) xor D(2) xor C(28) xor D(3) xor C(27) xor D(4) xor C(25)
xor C(31) xor D(0) xor D(6) xor C(24) xor C(30) xor D(1) xor D(7);
NewCRC(6):=C(30) xor D(1) xor C(29) xor D(2) xor C(28) xor D(3) xor C(26)
xor D(5) xor C(25) xor C(31) xor D(0) xor D(6);
NewCRC(7):=C(31) xor D(0) xor C(29) xor D(2) xor C(27) xor D(4) xor C(26)
xor D(5) xor C(24) xor D(7);
NewCRC(8):=C(0) xor C(28) xor D(3) xor C(27) xor D(4) xor C(25) xor D(6)
xor C(24) xor D(7);
NewCRC(9):=C(1) xor C(29) xor D(2) xor C(28) xor D(3) xor C(26) xor D(5)
xor C(25) xor D(6);
NewCRC(10):=C(2) xor C(29) xor D(2) xor C(27) xor D(4) xor C(26) xor D(5)
xor C(24) xor D(7);
NewCRC(11):=C(3) xor C(28) xor D(3) xor C(27) xor D(4) xor C(25) xor D(6)
xor C(24) xor D(7);
NewCRC(12):=C(4) xor C(29) xor D(2) xor C(28) xor D(3) xor C(26) xor D(5)
xor C(25) xor D(6) xor C(24) xor C(30) xor D(1) xor D(7);
NewCRC(13):=C(5) xor C(30) xor D(1) xor C(29) xor D(2) xor C(27) xor D(4)
xor C(26) xor D(5) xor C(25) xor C(31) xor D(0) xor D(6);
NewCRC(14):=C(6) xor C(31) xor D(0) xor C(30) xor D(1) xor C(28) xor D(3)
xor C(27) xor D(4) xor C(26) xor D(5);
NewCRC(15):=C(7) xor C(31) xor D(0) xor C(29) xor D(2) xor C(28) xor D(3)
xor C(27) xor D(4);
NewCRC(16):=C(8) xor C(29) xor D(2) xor C(28) xor D(3) xor C(24) xor D(7);
NewCRC(17):=C(9) xor C(30) xor D(1) xor C(29) xor D(2) xor C(25) xor D(6);
NewCRC(18):=C(10) xor C(31) xor D(0) xor C(30) xor D(1) xor C(26) xor D(5);
NewCRC(19):=C(11) xor C(31) xor D(0) xor C(27) xor D(4);
NewCRC(20):=C(12) xor C(28) xor D(3);
NewCRC(21):=C(13) xor C(29) xor D(2);
NewCRC(22):=C(14) xor C(24) xor D(7);
NewCRC(23):=C(15) xor C(25) xor D(6) xor C(24) xor C(30) xor D(1) xor D(7);
NewCRC(24):=C(16) xor C(26) xor D(5) xor C(25) xor C(31) xor D(0) xor D(6);
NewCRC(25):=C(17) xor C(27) xor D(4) xor C(26) xor D(5);
NewCRC(26):=C(18) xor C(28) xor D(3) xor C(27) xor D(4) xor C(24) xor C(30)
xor D(1) xor D(7);
NewCRC(27):=C(19) xor C(29) xor D(2) xor C(28) xor D(3) xor C(25) xor C(31)
xor D(0) xor D(6);
NewCRC(28):=C(20) xor C(30) xor D(1) xor C(29) xor D(2) xor C(26) xor D(5);
NewCRC(29):=C(21) xor C(31) xor D(0) xor C(30) xor D(1) xor C(27) xor D(4);
NewCRC(30):=C(22) xor C(31) xor D(0) xor C(28) xor D(3);
NewCRC(31):=C(23) xor C(29) xor D(2);
 
return NEWCRC;
end NEXTCRC32_D8;
 
-- Reverse the input vector.
function REVERSED(slv: std_logic_vector) return std_logic_vector is
variable result: std_logic_vector(slv'reverse_range);
begin
for i in slv'range loop
result(i) := slv(i);
end loop;
return result;
end REVERSED;
 
--constants
constant ADDRESS_BITS : integer := 11;
constant ADDRESS_MAX : integer := (2**ADDRESS_BITS) - 1;
 
--memories
type TX_MEMORY_TYPE is array (0 to 511) of
std_logic_vector(15 downto 0);
shared variable TX_MEMORY : TX_MEMORY_TYPE;
 
type RX_MEMORY_TYPE is array (0 to ADDRESS_MAX) of
std_logic_vector(15 downto 0);
shared variable RX_MEMORY : RX_MEMORY_TYPE;
 
type ADDRESS_ARRAY is array (0 to 31) of
unsigned(ADDRESS_BITS - 1 downto 0);
 
--state variables
type TX_PHY_STATE_TYPE is (WAIT_NEW_PACKET, PREAMBLE_0, PREAMBLE_1,
PREAMBLE_2, PREAMBLE_3, PREAMBLE_4, PREAMBLE_5, PREAMBLE_6, SFD,
SEND_DATA_HI, SEND_DATA_LO, SEND_CRC_3, SEND_CRC_2, SEND_CRC_1,
SEND_CRC_0, DONE_STATE);
signal TX_PHY_STATE : TX_PHY_STATE_TYPE;
 
type TX_PACKET_STATE_TYPE is(GET_LENGTH, GET_DATA, SEND_PACKET,
WAIT_NOT_DONE);
signal TX_PACKET_STATE : TX_PACKET_STATE_TYPE;
 
type RX_PHY_STATE_TYPE is (WAIT_START, PREAMBLE, DATA_HIGH, DATA_LOW,
END_OF_FRAME, NOTIFY_NEW_PACKET);
signal RX_PHY_STATE : RX_PHY_STATE_TYPE;
 
type RX_PACKET_STATE_TYPE is (WAIT_INITIALISE, WAIT_NEW_PACKET,
SEND_DATA, PREFETCH0, PREFETCH1, SEND_LENGTH);
signal RX_PACKET_STATE : RX_PACKET_STATE_TYPE;
 
--TX signals
signal TX_WRITE : std_logic;
signal TX_WRITE_DATA : std_logic_vector(15 downto 0);
signal TX_READ_DATA : std_logic_vector(15 downto 0);
signal TX_WRITE_ADDRESS : integer range 0 to 1513;
signal TX_WRITE_ADDRESS_DEL : integer range 0 to 1513;
signal TX_READ_ADDRESS : integer range 0 to 1513;
signal TX_CRC : std_logic_vector(31 downto 0);
signal TX_IN_COUNT : integer range 0 to 1513;
signal TX_OUT_COUNT : integer range 0 to 1513;
signal TX_PACKET_LENGTH : std_logic_vector(15 downto 0);
signal GO, GO_DEL, GO_SYNC : std_logic;
signal DONE, DONE_DEL, DONE_SYNC : std_logic;
signal S_TX_ACK : std_logic;
 
--RX signals
signal RX_WRITE_ADDRESS : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_READ_ADDRESS : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_START_ADDRESS : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_PACKET_LENGTH : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_START_ADDRESS_BUFFER : ADDRESS_ARRAY;
signal RX_PACKET_LENGTH_BUFFER : ADDRESS_ARRAY;
signal RX_WRITE_BUFFER : integer range 0 to 31;
signal RX_READ_BUFFER : integer range 0 to 31;
signal RX_BUFFER_BUSY : std_logic_vector(31 downto 0);
signal RX_BUFFER_BUSY_DEL : std_logic_vector(31 downto 0);
signal RX_BUFFER_BUSY_SYNC : std_logic_vector(31 downto 0);
signal RX_START_ADDRESS_SYNC : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_PACKET_LENGTH_SYNC : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_END_ADDRESS : unsigned(ADDRESS_BITS - 1 downto 0);
signal RX_WRITE_DATA : std_logic_vector(15 downto 0);
signal RX_WRITE_ENABLE : std_logic;
signal RX_ERROR : std_logic;
signal RX_CRC : std_logic_vector(31 downto 0);
signal RXD_D : std_logic_vector(7 downto 0);
signal RXDV_D : std_logic;
signal RXER_D : std_logic;
 
begin
--This process is in the local clock domain.
--It gets data and puts it into a RAM.
--Once a packets worth of data has been stored it is
--sent to the packet sending state machine.
TX_PACKET_FSM : process
begin
wait until rising_edge(CLK);
TX_WRITE <= '0';
case TX_PACKET_STATE is
 
when GET_LENGTH =>
S_TX_ACK <= '1';
if S_TX_ACK = '1' and TX_STB = '1' then
S_TX_ACK <= '0';
TX_PACKET_LENGTH <= TX;
TX_IN_COUNT <= 2;
TX_PACKET_STATE <= GET_DATA;
end if;
 
when GET_DATA =>
S_TX_ACK <= '1';
if S_TX_ACK = '1' and TX_STB = '1' then
TX_WRITE_DATA <= TX;
TX_WRITE <= '1';
if TX_IN_COUNT >= unsigned(TX_PACKET_LENGTH) then
TX_PACKET_STATE <= SEND_PACKET;
S_TX_ACK <= '0';
else
TX_WRITE_ADDRESS <= TX_WRITE_ADDRESS + 1;
TX_IN_COUNT <= TX_IN_COUNT + 2;
end if;
end if;
 
when SEND_PACKET =>
GO <= '1';
TX_WRITE_ADDRESS <= 0;
if DONE_SYNC = '1' then
GO <= '0';
TX_PACKET_STATE <= WAIT_NOT_DONE;
end if;
 
when WAIT_NOT_DONE =>
if DONE_SYNC = '0' then
TX_PACKET_STATE <= GET_LENGTH;
end if;
 
end case;
if RST = '1' then
TX_PACKET_STATE <= GET_LENGTH;
TX_WRITE_ADDRESS <= 0;
S_TX_ACK <= '0';
GO <= '0';
end if;
end process TX_PACKET_FSM;
 
TX_ACK <= S_TX_ACK;
 
 
--This process writes data into a dual port RAM
WRITE_DUAL_PORT_MEMORY : process
begin
wait until rising_edge(CLK);
TX_WRITE_ADDRESS_DEL <= TX_WRITE_ADDRESS;
if TX_WRITE = '1' then
TX_MEMORY(TX_WRITE_ADDRESS_DEL) := TX_WRITE_DATA;
end if;
end process;
 
--This process read data from a dual port RAM
READ_DUAL_PORT_MEMORY : process
begin
wait until rising_edge(CLK_125_MHZ);
TX_READ_DATA <= TX_MEMORY(TX_READ_ADDRESS);
end process;
 
--This process synchronises ethernet signals
--to the local clock domain
LOCAL_TO_CLK_125 : process
begin
wait until rising_edge(CLK_125_MHZ);
GO_DEL <= GO; GO_SYNC <= GO_DEL;
end process;
 
--This process synchronises local signals to the ethernet clock domain
CLK_125_TO_LOCAL : process
begin
wait until rising_edge(CLK);
DONE_DEL <= DONE; DONE_SYNC <= DONE_DEL;
end process;
 
--Transmit the stored packet via the phy.
TX_PHY_FSM : process
begin
wait until rising_edge(CLK_125_MHZ);
case TX_PHY_STATE is
 
when WAIT_NEW_PACKET =>
if GO_SYNC = '1' then
TX_PHY_STATE <= PREAMBLE_0;
TX_READ_ADDRESS <= 0;
TX_OUT_COUNT <= to_integer(unsigned(TX_PACKET_LENGTH)-1);
end if;
 
when PREAMBLE_0 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_1;
TXEN <= '1';
 
when PREAMBLE_1 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_2;
 
when PREAMBLE_2 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_3;
 
when PREAMBLE_3 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_4;
 
when PREAMBLE_4 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_5;
 
when PREAMBLE_5 =>
TXD <= X"55";
TX_PHY_STATE <= PREAMBLE_6;
 
when PREAMBLE_6 =>
TXD <= X"55";
TX_PHY_STATE <= SFD;
when SFD =>
TXD <= X"D5";
TX_PHY_STATE <= SEND_DATA_HI;
TX_CRC <= X"FFFFFFFF";
when SEND_DATA_HI =>
TX_CRC <= NEXTCRC32_D8(TX_READ_DATA(15 downto 8), TX_CRC);
TXD <= TX_READ_DATA(15 downto 8);
If TX_OUT_COUNT = 0 then
TX_PHY_STATE <= SEND_CRC_3;
else
TX_PHY_STATE <= SEND_DATA_LO;
TX_READ_ADDRESS <= TX_READ_ADDRESS + 1;
TX_OUT_COUNT <= TX_OUT_COUNT - 1;
end if;
when SEND_DATA_LO =>
TX_CRC <= NEXTCRC32_D8(TX_READ_DATA(7 downto 0), TX_CRC);
TXD <= TX_READ_DATA(7 downto 0);
If TX_OUT_COUNT = 0 then
TX_PHY_STATE <= SEND_CRC_3;
else
TX_PHY_STATE <= SEND_DATA_HI;
TX_OUT_COUNT <= TX_OUT_COUNT - 1;
end if;
when SEND_CRC_3 =>
TXD <= not REVERSED(TX_CRC(31 downto 24));
TX_PHY_STATE <= SEND_CRC_2;
 
when SEND_CRC_2 =>
TXD <= not REVERSED(TX_CRC(23 downto 16));
TX_PHY_STATE <= SEND_CRC_1;
 
when SEND_CRC_1 =>
TXD <= not REVERSED(TX_CRC(15 downto 8));
TX_PHY_STATE <= SEND_CRC_0;
 
when SEND_CRC_0 =>
TXD <= not REVERSED(TX_CRC(7 downto 0));
TX_PHY_STATE <= DONE_STATE;
when DONE_STATE =>
TXEN <= '0';
DONE <= '1';
if GO_SYNC = '0' then
TX_PHY_STATE <= WAIT_NEW_PACKET;
DONE <= '0';
end if;
end case;
if RST = '1' then
TXEN <= '0';
TX_PHY_STATE <= WAIT_NEW_PACKET;
DONE <= '0';
TXD <= (others => '0');
end if;
end process TX_PHY_FSM;
 
TXER <= '0';
GTXCLK <= CLK_125_MHZ;
--This process reads data out of the phy and puts it into a buffer.
--There are many buffers on the RX side to cope with data arriving at
--a high rate. If a very large packet is received, followed by many small
--packets, a large number of packets need to be stored.
RX_PHY_FSM : process
begin
wait until rising_edge(RXCLK);
RX_WRITE_ENABLE <= '0';
RXDV_D <= RXDV;
RXER_D <= RXER;
RXD_D <= RXD;
case RX_PHY_STATE is
 
when WAIT_START =>
if RXDV_D = '1' and RXD_D = X"55" then
RX_PHY_STATE <= PREAMBLE;
RX_ERROR <= '0';
end if;
 
when PREAMBLE =>
if RXD_D = X"d5" then
RX_PHY_STATE <= DATA_HIGH;
RX_START_ADDRESS <= RX_WRITE_ADDRESS;
RX_PACKET_LENGTH <= to_unsigned(0, ADDRESS_BITS);
RX_CRC <= X"ffffffff";
elsif RXD_D /= X"55" or RXDV_D = '0' then
RX_PHY_STATE <= WAIT_START;
end if;
 
when DATA_HIGH =>
RX_WRITE_DATA(15 downto 8) <= RXD_D;
if RXDV_D = '1' then
RX_PACKET_LENGTH <= RX_PACKET_LENGTH + 1;
RX_PHY_STATE <= DATA_LOW;
RX_CRC <= nextCRC32_D8(RXD_D, RX_CRC);
else
RX_PHY_STATE <= END_OF_FRAME;
end if;
 
when DATA_LOW =>
RX_WRITE_DATA(7 downto 0) <= RXD_D;
RX_WRITE_ENABLE <= '1';
if RXDV_D = '1' then
RX_PACKET_LENGTH <= RX_PACKET_LENGTH + 1;
RX_PHY_STATE <= DATA_HIGH;
RX_CRC <= nextCRC32_D8(RXD_D, RX_CRC);
else
RX_PHY_STATE <= END_OF_FRAME;
end if;
 
when END_OF_FRAME =>
if RX_ERROR = '1' then
RX_PHY_STATE <= WAIT_START;
elsif RX_PACKET_LENGTH < 64 then
RX_PHY_STATE <= WAIT_START;
elsif RX_PACKET_LENGTH > 1518 then
RX_PHY_STATE <= WAIT_START;
elsif RX_CRC /= X"C704dd7B" then
RX_PHY_STATE <= WAIT_START;
else
RX_PHY_STATE <= NOTIFY_NEW_PACKET;
end if;
 
when NOTIFY_NEW_PACKET =>
RX_PHY_STATE <= WAIT_START;
RX_START_ADDRESS_BUFFER(RX_WRITE_BUFFER) <= RX_START_ADDRESS;
RX_PACKET_LENGTH_BUFFER(RX_WRITE_BUFFER) <= RX_PACKET_LENGTH;
if RX_WRITE_BUFFER = 31 then
RX_WRITE_BUFFER <= 0;
else
RX_WRITE_BUFFER <= RX_WRITE_BUFFER + 1;
end if;
end case;
 
if RXER_D = '1' then
RX_ERROR <= '1';
end if;
 
if RST = '1' then
RX_PHY_STATE <= WAIT_START;
end if;
end process RX_PHY_FSM;
 
--generate a signal for each buffer to indicate that is is being used.
GENERATE_BUFFER_BUSY : process
begin
wait until rising_edge(RXCLK);
for I in 0 to 31 loop
if I = RX_WRITE_BUFFER then
RX_BUFFER_BUSY(I) <= '1';
else
RX_BUFFER_BUSY(I) <= '0';
end if;
end loop;
end process GENERATE_BUFFER_BUSY;
 
--This is the memory that implements the RX buffers
WRITE_RX_MEMORY : process
begin
wait until rising_edge(RXCLK);
if RX_WRITE_ENABLE = '1' then
RX_MEMORY(to_integer(RX_WRITE_ADDRESS)) := RX_WRITE_DATA;
RX_WRITE_ADDRESS <= RX_WRITE_ADDRESS + 1;
end if;
if RST = '1' then
RX_WRITE_ADDRESS <= (others => '0');
end if;
end process WRITE_RX_MEMORY;
 
SYNCHRONISE_BUFFER_BUSY : process
begin
wait until rising_edge(CLK);
RX_BUFFER_BUSY_DEL <= RX_BUFFER_BUSY;
RX_BUFFER_BUSY_SYNC <= RX_BUFFER_BUSY_DEL;
end process SYNCHRONISE_BUFFER_BUSY;
 
--CLK __/""\__/" _/" "\__/""\
--RX_BUFFER_BUSY_SYNC[0] ""\_______ ____________
--RX_BUFFER_BUSY_SYNC[1] ________/" "\__________
--RX_BUFFER_BUSY_SYNC[2] __________ _______/""""
-- ^
-- Start to read packet 0 here.
-- Note: since RX_BUFFER_BUSY originates in a different clock domain,
-- it is possible that a clock cycle or so could elapse between
-- RX_BUFFER_BUSY_SYNC[0] becoming low and RX_BUFFER_BUSY_SYNC[1] becoming
-- high. We are relying on the delay through the state machine to be
-- long enough that we don't try to read BUFFER1 during this period.
RX_PACKET_FSM : process
begin
wait until rising_edge(CLK);
case RX_PACKET_STATE is
 
when WAIT_INITIALISE =>
if RX_BUFFER_BUSY_SYNC(0) = '1' then
RX_PACKET_STATE <= WAIT_NEW_PACKET;
RX_READ_BUFFER <= 0;
end if;
 
when WAIT_NEW_PACKET =>
if RX_BUFFER_BUSY_SYNC(RX_READ_BUFFER) = '0' then
RX_PACKET_STATE <= SEND_LENGTH;
RX_START_ADDRESS_SYNC <= RX_START_ADDRESS_BUFFER(RX_READ_BUFFER);
RX_PACKET_LENGTH_SYNC <= RX_PACKET_LENGTH_BUFFER(RX_READ_BUFFER);
RX <=
std_logic_vector(
resize(RX_PACKET_LENGTH_BUFFER(RX_READ_BUFFER)-4, 16));
RX_STB <= '1';
end if;
when SEND_LENGTH =>
if RX_ACK = '1' then
RX_PACKET_STATE <= PREFETCH0;
RX_STB <= '0';
end if;
when PREFETCH0 =>
RX_READ_ADDRESS <= RX_START_ADDRESS_SYNC;
RX_END_ADDRESS <= RX_START_ADDRESS_SYNC + (RX_PACKET_LENGTH_SYNC-3)/2;
RX_PACKET_STATE <= PREFETCH1;
when PREFETCH1 =>
RX_READ_ADDRESS <= RX_READ_ADDRESS + 1;
RX <= RX_MEMORY(to_integer(RX_READ_ADDRESS));
RX_STB <= '1';
RX_PACKET_STATE <= SEND_DATA;
when SEND_DATA =>
if RX_ACK = '1' then
RX_READ_ADDRESS <= RX_READ_ADDRESS + 1;
RX <= RX_MEMORY(to_integer(RX_READ_ADDRESS));
if RX_READ_ADDRESS = RX_END_ADDRESS then --don't send last packet
RX_STB <= '0';
RX_PACKET_STATE <= WAIT_NEW_PACKET;
if RX_READ_BUFFER = 31 then
RX_READ_BUFFER <= 0;
else
RX_READ_BUFFER <= RX_READ_BUFFER + 1;
end if;
end if;
end if;
end case;
if RST = '1' then
RX_STB <= '0';
RX_PACKET_STATE <= WAIT_INITIALISE;
end if;
end process RX_PACKET_FSM;
 
----------------------------------------------------------------------
-- RESET PHY CHIP
----------------------------------------------------------------------
PHY_RESET <= not RST;
end architecture RTL;
/source/user_design_atlys.c
0,0 → 1,170
////////////////////////////////////////////////////////////////////////////////
//
// CHIPS-2.0 USER DESIGN
//
// :Author: Jonathan P Dawson
// :Date: 17/10/2013
// :email: chips@jondawson.org.uk
// :license: MIT
// :Copyright: Copyright (C) Jonathan P Dawson 2013
//
// Simple web app demo.
//
////////////////////////////////////////////////////////////////////////////////
 
void put_socket(unsigned i){
output_socket(i);
}
void stdout_put_char(unsigned i){
output_rs232_tx(i);
}
 
#include "print.h"
#include "HTTP.h"
 
int find(unsigned string[], unsigned search, unsigned start, unsigned end){
int value = start;
while(string[value]){
print_decimal(string[value]); print_string("\n");
print_decimal(value); print_string("\n");
if(value == end) return -1;
if(string[value] == search) return value;
value++;
}
return -1;
}
 
void user_design()
{
//simple echo application
unsigned length;
unsigned i, index;
unsigned data[1460];
unsigned word;
unsigned switches = 0;
unsigned buttons = 0;
unsigned leds = 0;
unsigned start, end;
 
unsigned page[] =
"<html>\
<head>\
<title>Chips-2.0 ATLYS Demo</title>\
</head>\
<body>\
<h1>Chips-2.0 ATLYS Demo</h1>\
<p>Welcome to the Chips-2.0 ATLYS Demo!</p>\
<p>Switch Status: 00000000</p>\
<p>Button Status: 0000</p>\
<form>\
<input type=\"checkbox\" name=\"led1\" value=\"A\">led 0</input>\
<input type=\"checkbox\" name=\"led2\" value=\"B\">led 1</input>\
<input type=\"checkbox\" name=\"led3\" value=\"C\">led 2</input>\
<input type=\"checkbox\" name=\"led4\" value=\"D\">led 3</input>\
<input type=\"checkbox\" name=\"led4\" value=\"E\">led 4</input>\
<input type=\"checkbox\" name=\"led4\" value=\"F\">led 5</input>\
<input type=\"checkbox\" name=\"led4\" value=\"G\">led 6</input>\
<input type=\"checkbox\" name=\"led4\" value=\"H\">led 7</input>\
<button type=\"sumbit\" value=\"Submit\">Update LEDs</button>\
</form>\
<p>This <a href=\"https://github.com/dawsonjon/Chips-Demo\">project</a>\
is powered by <a href=\"https://github.com/dawsonjon/Chips-2.0\">Chips-2.0</a>.</p>\
</body>\
</html>";
 
print_string("Welcome to the Atlys Chips-2.0 demo!\n");
print_string("Connect your web browser to 192.168.1.1\n");
while(1){
 
length = input_socket();
index = 0;
for(i=0;i<length;i+=2){
word = input_socket();
data[index] = (word >> 8) & 0xff;
index++;
data[index] = (word) & 0xff;
index++;
}
 
//Get LED values
//==============
 
if( data[0] == 'G'
&& data[1] == 'E'
&& data[2] == 'T'
&& data[3] == ' '
&& data[4] == '/'
&& (data[5] == '?' || data[5] == ' ')){
start=5;
end=find(data, ' ', start, index);
leds = 0;
if(find(data, 'A', start, end) != -1) leds |= 1;
if(find(data, 'B', start, end) != -1) leds |= 2;
if(find(data, 'C', start, end) != -1) leds |= 4;
if(find(data, 'D', start, end) != -1) leds |= 8;
if(find(data, 'E', start, end) != -1) leds |= 16;
if(find(data, 'F', start, end) != -1) leds |= 32;
if(find(data, 'G', start, end) != -1) leds |= 64;
if(find(data, 'H', start, end) != -1) leds |= 128;
output_leds(leds);
 
//read switch values
//==================
switches = ~input_switches();
//find first ':'
index = find(page, ':', 0, 1460);
index+=2;
//insert switch values
if(switches & 128) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 64) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 32) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 16) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 8) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 4) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 2) page[index] = '0';
else page[index] = '1';
index ++;
if(switches & 1) page[index] = '0';
else page[index] = '1';
 
//read button values
//==================
buttons = ~input_buttons();
//find next ':'
index = find(page, ':', index+1, 1460);
index+=2;
//insert button values
if(buttons & 1) page[index] = '0';
else page[index] = '1';
index ++;
if(buttons & 2) page[index] = '0';
else page[index] = '1';
index ++;
if(buttons & 4) page[index] = '0';
else page[index] = '1';
index ++;
if(buttons & 8) page[index] = '0';
else page[index] = '1';
 
HTTP_OK(page);
} else {
HTTP_Not_Found();
}
 
}
 
//dummy access to peripherals
index = input_rs232_rx();
}
/source/serial_in.vhd
0,0 → 1,198
--------------------------------------------------------------------------------
---
--- SERIAL INPUT
---
--- :Author: Jonathan P Dawson
--- :Date: 17/10/2013
--- :email: chips@jondawson.org.uk
--- :license: MIT
--- :Copyright: Copyright (C) Jonathan P Dawson 2013
---
--- A Serial Input Component
---
--------------------------------------------------------------------------------
---
---Serial Input
---============
---
---Read a stream of data from a serial UART
---
---Outputs
-----------
---
--- + OUT1 : Serial data stream
---
---Generics
-----------
---
--- + baud_rate
--- + clock frequency
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity SERIAL_INPUT is
 
generic(
CLOCK_FREQUENCY : integer;
BAUD_RATE : integer
);
port(
CLK : in std_logic;
RST : in std_logic;
RX : in std_logic;
OUT1 : out std_logic_vector(7 downto 0);
OUT1_STB : out std_logic;
OUT1_ACK : in std_logic
);
 
end entity SERIAL_INPUT;
 
architecture RTL of SERIAL_INPUT is
 
type SERIAL_IN_STATE_TYPE is (IDLE, START, RX0, RX1, RX2, RX3, RX4, RX5, RX6, RX7, STOP, OUTPUT_DATA);
signal STATE : SERIAL_IN_STATE_TYPE;
signal STREAM : std_logic_vector(7 downto 0);
signal STREAM_STB : std_logic;
signal STREAM_ACK : std_logic;
signal COUNT : integer Range 0 to 3;
signal BIT_SPACING : integer Range 0 to 15;
signal INT_SERIAL : std_logic;
signal SERIAL_DEGLITCH : std_logic_Vector(1 downto 0);
constant CLOCK_DIVIDER : unsigned(11 downto 0) := To_unsigned(CLOCK_FREQUENCY/(BAUD_RATE * 16), 12);
signal BAUD_COUNT : unsigned(11 downto 0);
signal X16CLK_EN : std_logic;
 
begin
 
process
begin
wait until rising_edge(CLK);
if BAUD_COUNT = CLOCK_DIVIDER then
BAUD_COUNT <= (others => '0');
X16CLK_EN <= '1';
else
BAUD_COUNT <= BAUD_COUNT + 1;
X16CLK_EN <= '0';
end if;
if RST = '1' then
BAUD_COUNT <= (others => '0');
X16CLK_EN <= '0';
end if;
end process;
 
process
begin
wait until rising_edge(CLK);
SERIAL_DEGLITCH <= SERIAL_DEGLITCH(0) & RX;
if X16CLK_EN = '1' then
if SERIAL_DEGLITCH(1) = '0' then
if COUNT = 0 then
INT_SERIAL <= '0';
else
COUNT <= COUNT - 1;
end if;
else
if COUNT = 3 then
INT_SERIAL <= '1';
else
COUNT <= COUNT + 1;
end if;
end if;
end if;
if RST = '1' then
SERIAL_DEGLITCH <= "11";
end if;
end process;
 
process
begin
wait until rising_edge(CLK);
if X16CLK_EN = '1' then
if BIT_SPACING = 15 then
BIT_SPACING <= 0;
else
BIT_SPACING <= BIT_SPACING + 1;
end if;
end if;
case STATE is
when IDLE =>
BIT_SPACING <= 0;
if X16CLK_EN = '1' and INT_SERIAL = '0' then
STATE <= START;
end if;
when START =>
if X16CLK_EN = '1' and BIT_SPACING = 7 then
BIT_SPACING <= 0;
STATE <= RX0;
end if;
when RX0 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(0) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX1;
end if;
when RX1 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(1) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX2;
end if;
when RX2 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(2) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX3;
end if;
when RX3 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(3) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX4;
end if;
when RX4 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(4) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX5;
end if;
when RX5 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(5) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX6;
end if;
when RX6 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(6) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= RX7;
end if;
when RX7 =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
OUT1(7) <= INT_SERIAL;
BIT_SPACING <= 0;
STATE <= STOP;
end if;
when STOP =>
if X16CLK_EN = '1' and BIT_SPACING = 15 then
BIT_SPACING <= 0;
STATE <= OUTPUT_DATA;
OUT1_STB <= '1';
end if;
when OUTPUT_DATA =>
if OUT1_ACK = '1' then
OUT1_STB <= '0';
STATE <= IDLE;
end if;
when others =>
STATE <= IDLE;
end case;
if RST = '1' then
STATE <= IDLE;
OUT1_STB <= '0';
end if;
end process;
end architecture RTL;
/source/HTTP.h
0,0 → 1,155
////////////////////////////////////////////////////////////////////////////////
//
// CHIPS-2.0 HTTP
//
// :Author: Jonathan P Dawson
// :Date: 17/10/2013
// :email: chips@jondawson.org.uk
// :license: MIT
// :Copyright: Copyright (C) Jonathan P Dawson 2013
//
// Constuct an HTTP response for simple web app.
//
////////////////////////////////////////////////////////////////////////////////
unsigned socket_high = 1;
unsigned socket_data;
 
void socket_put_char(char x){
if(socket_high){
socket_high = 0;
socket_data = x << 8;
} else {
socket_high = 1;
socket_data |= x & 0xff;
put_socket(socket_data);
}
}
 
void socket_flush(){
if(!socket_high) put_socket(socket_data);
socket_high = 1;
}
 
void socket_put_string(unsigned string[]){
unsigned i;
while(string[i]){
socket_put_char(string[i]);
i++;
}
}
 
void socket_put_decimal(unsigned value){
unsigned digit_0 = 0;
unsigned digit_1 = 0;
unsigned digit_2 = 0;
unsigned digit_3 = 0;
unsigned digit_4 = 0;
unsigned significant = 0;
 
while(value >= 10000){
digit_4++;
value -= 10000;
}
if(digit_4 | significant){
socket_put_char(0x30 | digit_4);
significant = 1;
}
while(value >= 1000){
digit_3++;
value -= 1000;
}
if(digit_3 | significant) {
socket_put_char(0x30 | digit_3);
significant = 1;
}
while(value >= 100){
digit_2++;
value -= 100;
}
if(digit_2 | significant){
socket_put_char(0x30 | digit_2);
significant = 1;
}
while(value >= 10){
digit_1++;
value -= 10;
}
if(digit_1 | significant){
socket_put_char(0x30 | digit_1);
significant = 1;
}
while(value >= 1){
digit_0++;
value -= 1;
}
socket_put_char(0x30 | digit_0);
}
 
void HTTP_Not_Found(){
unsigned header_length;
unsigned header[] =
"HTTP/1.1 404 Not Found\r\n\
Date: Thu Oct 31 19:16:00 2013\r\n\
Server: chips-web/0.0\r\n\
Content-Type: text/html\r\n\
Content-Length: 0\r\n\r\n";
 
//count header length
header_length = 0;
while(header[header_length]) header_length++;
put_socket(header_length);
socket_put_string(header);
socket_flush();
}
 
void HTTP_OK(int body[]){
unsigned header_length;
unsigned body_length;
unsigned length, index, packet_count;
unsigned header[] =
"HTTP/1.1 200 OK\r\n\
Date: Thu Oct 31 19:16:00 2013\r\n\
Server: chips-web/0.0\r\n\
Content-Type: text/html\r\n\
Content-Length: ";
 
//count body length
body_length = 0;
while(body[body_length]) body_length++;
//count header length
header_length = 0;
while(header[header_length]) header_length++;
 
//count total length
length = header_length + 5;
//header length depends on body length
if(body_length > 9) length++;
if(body_length > 99) length++;
if(body_length > 999) length++;
//Send length to server
put_socket(length);
//Send header to server
socket_put_string(header);
socket_put_decimal(body_length);
socket_put_string("\r\n\r\n");
socket_flush();
 
length = body_length;
index = 0;
packet_count = 0;
while(length >= 1046){
length -= 1046;
put_socket(1046);
for(packet_count=0; packet_count<1046; packet_count++){
socket_put_char(body[index]);
index++;
}
socket_flush();
}
put_socket(length);
for(packet_count=0; packet_count<length; packet_count++){
socket_put_char(body[index]);
index++;
}
socket_flush();
}
/source/server_test.c
0,0 → 1,17
void put_eth(unsigned int i){
file_write(i, "ethernet.resp");
}
void put_socket(unsigned int i){
file_write(i, "socket.resp");
}
unsigned get_eth(){
return file_read("ethernet.stim");
}
unsigned rdy_eth(){
return 1;
}
unsigned get_socket(){
return file_read("socket.stim");
}
 
#include "server.h"
/source/serial_out.vhd
0,0 → 1,144
--------------------------------------------------------------------------------
---
--- SERIAL OUTPUT
---
--- :Author: Jonathan P Dawson
--- :Date: 17/10/2013
--- :email: chips@jondawson.org.uk
--- :license: MIT
--- :Copyright: Copyright (C) Jonathan P Dawson 2013
---
--- A Serial Output Component
---
--------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity serial_output is
 
generic(
CLOCK_FREQUENCY : integer;
BAUD_RATE : integer
);
port(
CLK : in std_logic;
RST : in std_logic;
TX : out std_logic := '1';
IN1 : in std_logic_vector(7 downto 0);
IN1_STB : in std_logic;
IN1_ACK : out std_logic := '1'
);
 
end entity serial_output;
 
architecture RTL of serial_output is
 
constant CLOCK_DIVIDER : Unsigned(11 downto 0) := To_unsigned(CLOCK_FREQUENCY/BAUD_RATE, 12);
signal BAUD_COUNT : Unsigned(11 downto 0) := (others => '0');
signal DATA : std_logic_vector(7 downto 0) := (others => '0');
signal X16CLK_EN : std_logic := '0';
signal S_IN1_ACK : std_logic := '0';
 
type STATE_TYPE is (IDLE, START, WAIT_EN, TX0, TX1, TX2, TX3, TX4, TX5, TX6, TX7, STOP);
signal STATE : STATE_TYPE := IDLE;
 
begin
 
process
begin
wait until rising_edge(CLK);
if BAUD_COUNT = CLOCK_DIVIDER - 1 then
BAUD_COUNT <= (others => '0');
X16CLK_EN <= '1';
else
BAUD_COUNT <= BAUD_COUNT + 1;
X16CLK_EN <= '0';
end if;
if RST = '1' then
BAUD_COUNT <= (others => '0');
X16CLK_EN <= '0';
end if;
end process;
 
process
begin
wait until rising_edge(CLK);
case STATE is
when IDLE =>
TX <= '1';
S_IN1_ACK <= '1';
if S_IN1_ACK = '1' and IN1_STB = '1' then
S_IN1_ACK <= '0';
DATA <= IN1;
STATE <= WAIT_EN;
end if;
when WAIT_EN =>
if X16CLK_EN = '1' then
STATE <= START;
end if;
when START =>
if X16CLK_EN = '1' then
STATE <= TX0;
end if;
TX <= '0';
when TX0 =>
if X16CLK_EN = '1' then
STATE <= TX1;
end if;
TX <= DATA(0);
when TX1 =>
if X16CLK_EN = '1' then
STATE <= TX2;
end if;
TX <= DATA(1);
when TX2 =>
if X16CLK_EN = '1' then
STATE <= TX3;
end if;
TX <= DATA(2);
when TX3 =>
if X16CLK_EN = '1' then
STATE <= TX4;
end if;
TX <= DATA(3);
when TX4 =>
if X16CLK_EN = '1' then
STATE <= TX5;
end if;
TX <= DATA(4);
when TX5 =>
if X16CLK_EN = '1' then
STATE <= TX6;
end if;
TX <= DATA(5);
when TX6 =>
if X16CLK_EN = '1' then
STATE <= TX7;
end if;
TX <= DATA(6);
when TX7 =>
if X16CLK_EN = '1' then
STATE <= STOP;
end if;
TX <= DATA(7);
when STOP =>
if X16CLK_EN = '1' then
STATE <= IDLE;
end if;
TX <= '1';
when others =>
STATE <= IDLE;
end case;
if RST = '1' then
STATE <= IDLE;
TX <= '1';
S_IN1_ACK <= '0';
end if;
end process;
 
IN1_ACK <= S_IN1_ACK;
 
end architecture RTL;
/source/server.c
0,0 → 1,29
////////////////////////////////////////////////////////////////////////////////
//
// CHIPS-2.0 TCP/IP SERVER
//
// :Author: Jonathan P Dawson
// :Date: 17/10/2013
// :email: chips@jondawson.org.uk
// :license: MIT
// :Copyright: Copyright (C) Jonathan P Dawson 2013
//
// A TCP/IP stack that supports a single socket connection.
//
////////////////////////////////////////////////////////////////////////////////
void put_eth(unsigned i){
output_eth_tx(i);
}
void put_socket(unsigned i){
output_socket(i);
}
unsigned get_eth(){
return input_eth_rx();
}
unsigned rdy_eth(){
return ready_eth_rx();
}
unsigned get_socket(){
return input_socket();
}
#include "server.h"
/source/server.h
0,0 → 1,664
////////////////////////////////////////////////////////////////////////////////
//
// CHIPS-2.0 TCP/IP SERVER
//
// :Author: Jonathan P Dawson
// :Date: 17/10/2013
// :email: chips@jondawson.org.uk
// :license: MIT
// :Copyright: Copyright (C) Jonathan P Dawson 2013
//
// A TCP/IP stack that supports a single socket connection.
//
////////////////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////////////////
// TCP-IP User Settings
//
 
unsigned local_mac_address_hi = 0x0001u;
unsigned local_mac_address_med = 0x0203u;
unsigned local_mac_address_lo = 0x0405u;
unsigned local_ip_address_hi = 0xc0A8u;//192/168
unsigned local_ip_address_lo = 0x0101u;//1/1
unsigned local_port = 80u;//http
 
////////////////////////////////////////////////////////////////////////////////
// TCP-IP GLOBALS
//
 
unsigned tx_packet[512];
 
////////////////////////////////////////////////////////////////////////////////
// Checksum calculation routines
//
//store checksum in a global variable
//unsigneds are 16 bits, so use an array of 2 to hold a 32 bit number
long unsigned checksum;
//Reset checksum before calculation
//
void reset_checksum(){
checksum = 0;
}
//Add 16 bit data value to 32 bit checksum value
//
void add_checksum(unsigned data){
checksum += data;
if(checksum & 0x10000ul){
checksum &= 0xffffu;
checksum += 1;
}
}
//Retrieve the calculated checksum
//
unsigned check_checksum(){
return ~checksum;
}
 
////////////////////////////////////////////////////////////////////////////////
// UTILITY FUNCTIONS
//
 
unsigned calc_ack(unsigned ack[], unsigned seq[], unsigned length){
//given a two word sequence number and a one word length
//calculate a two word acknowledgement number
//check whether we have new data or not
unsigned new_ack_0;
unsigned new_ack_1;
unsigned return_value = 0;
new_ack_0 = seq[0] + length;
new_ack_1 = seq[1];
if(new_ack_0 < length) new_ack_1 = new_ack_1 + 1;
 
//Is this data we have allready acknowledged?
if((new_ack_0 != ack[0]) || (new_ack_1 != ack[1])){
ack[0] = new_ack_0;
ack[1] = new_ack_1;
return_value = 1;
}
return return_value;
}
////////////////////////////////////////////////////////////////////////////////
// Data Link Layer - Ethernet
//
 
void put_ethernet_packet(
unsigned packet[],
unsigned number_of_bytes,
unsigned destination_mac_address_hi,
unsigned destination_mac_address_med,
unsigned destination_mac_address_lo,
unsigned protocol){
 
unsigned byte, index;
report(number_of_bytes);
 
//set up ethernet header
packet[0] = destination_mac_address_hi;
packet[1] = destination_mac_address_med;
packet[2] = destination_mac_address_lo;
packet[3] = local_mac_address_hi;
packet[4] = local_mac_address_med;
packet[5] = local_mac_address_lo;
packet[6] = protocol;
 
put_eth(number_of_bytes);
index = 0;
for(byte=0; byte<number_of_bytes; byte+=2){
put_eth(packet[index]);
index ++;
}
}
 
//Get a packet from the ethernet interface
//Will reply to arp requests
//returns the number of bytes read which may be 0
unsigned get_ethernet_packet(unsigned packet[]){
 
unsigned number_of_bytes, index;
unsigned byte;
 
if(!rdy_eth()) return 0;
 
number_of_bytes = get_eth();
index = 0;
for(byte=0; byte<number_of_bytes; byte+=2){
packet[index] = get_eth();
index ++;
}
 
//Filter out packets not meant for us
if(packet[0] != local_mac_address_hi && packet[0] != 0xffffu) return 0;
if(packet[1] != local_mac_address_med && packet[1] != 0xffffu) return 0;
if(packet[2] != local_mac_address_lo && packet[2] != 0xffffu) return 0;
 
//Process ARP requests within the data link layer
if (packet[6] == 0x0806){ //ARP
//respond to requests
if (packet[10] == 0x0001){
//construct and send an ARP response
tx_packet[7] = 0x0001; //HTYPE ethernet
tx_packet[8] = 0x0800; //PTYPE IPV4
tx_packet[9] = 0x0604; //HLEN, PLEN
tx_packet[10] = 0x0002; //OPER=REPLY
tx_packet[11] = local_mac_address_hi; //SENDER_HARDWARE_ADDRESS
tx_packet[12] = local_mac_address_med; //SENDER_HARDWARE_ADDRESS
tx_packet[13] = local_mac_address_lo; //SENDER_HARDWARE_ADDRESS
tx_packet[14] = local_ip_address_hi; //SENDER_PROTOCOL_ADDRESS
tx_packet[15] = local_ip_address_lo; //SENDER_PROTOCOL_ADDRESS
tx_packet[16] = packet[11]; //TARGET_HARDWARE_ADDRESS
tx_packet[17] = packet[12]; //
tx_packet[18] = packet[13]; //
tx_packet[19] = packet[14]; //TARGET_PROTOCOL_ADDRESS
tx_packet[20] = packet[15]; //
put_ethernet_packet(
tx_packet,
64,
packet[11],
packet[12],
packet[13],
0x0806);
}
return 0;
}
return number_of_bytes;
}
 
unsigned arp_ip_hi[16];
unsigned arp_ip_lo[16];
unsigned arp_mac_0[16];
unsigned arp_mac_1[16];
unsigned arp_mac_2[16];
unsigned arp_pounsigneder = 0;
 
//return the location of the ip address in the arp cache table
unsigned get_arp_cache(unsigned ip_hi, unsigned ip_lo){
 
unsigned number_of_bytes;
unsigned byte;
unsigned packet[16];
unsigned i;
 
//Is the requested IP in the ARP cache?
for(i=0; i<16; i++){
if(arp_ip_hi[i] == ip_hi && arp_ip_lo[i] == ip_lo){
return i;
}
}
 
//It is not, so send an arp request
tx_packet[7] = 0x0001u; //HTYPE ethernet
tx_packet[8] = 0x0800u; //PTYPE IPV4
tx_packet[9] = 0x0604u; //HLEN, PLEN
tx_packet[10] = 0x0001u; //OPER=REQUEST
tx_packet[11] = local_mac_address_hi; //SENDER_HARDWARE_ADDRESS
tx_packet[12] = local_mac_address_med; //SENDER_HARDWARE_ADDRESS
tx_packet[13] = local_mac_address_lo; //SENDER_HARDWARE_ADDRESS
tx_packet[14] = local_ip_address_hi; //SENDER_PROTOCOL_ADDRESS
tx_packet[15] = local_ip_address_lo; //SENDER_PROTOCOL_ADDRESS
tx_packet[19] = ip_hi; //TARGET_PROTOCOL_ADDRESS
tx_packet[20] = ip_lo; //
put_ethernet_packet(
tx_packet,
64u,
0xffffu, //broadcast via ethernet
0xffffu,
0xffffu,
0x0806u);
 
//wait for a response
while(1){
 
number_of_bytes = get_eth();
i = 0;
for(byte=0; byte<number_of_bytes; byte+=2){
//only keep the part of the packet we care about
if(i < 16){
packet[i] = get_eth();
} else {
get_eth();
}
i++;
}
 
//Process ARP requests within the data link layer
if (packet[6] == 0x0806 && packet[10] == 0x0002){
if (packet[14] == ip_hi && packet[15] == ip_lo){
arp_ip_hi[arp_pounsigneder] = ip_hi;
arp_ip_lo[arp_pounsigneder] = ip_lo;
arp_mac_0[arp_pounsigneder] = packet[11];
arp_mac_1[arp_pounsigneder] = packet[12];
arp_mac_2[arp_pounsigneder] = packet[13];
i = arp_pounsigneder;
arp_pounsigneder++;
if(arp_pounsigneder == 16) arp_pounsigneder = 0;
return i;
}
}
}
}
 
////////////////////////////////////////////////////////////////////////////////
// Network Layer - Internet Protocol
//
 
void put_ip_packet(unsigned packet[], unsigned total_length, unsigned protocol, unsigned ip_hi, unsigned ip_lo){
unsigned number_of_bytes, i, arp_cache;
 
//see if the requested IP address is in the arp cache
arp_cache = get_arp_cache(ip_hi, ip_lo);
 
//Form IP header
packet[7] = 0x4500; //Version 4 header length 5x32
packet[8] = total_length; //IP data + header
packet[9] = 0x0000; //Identification
packet[10] = 0x4000; //don't fragment
packet[11] = 0xFF00u | protocol; //ttl|protocol
packet[12] = 0x0000; //checksum
packet[13] = local_ip_address_hi;//source_high
packet[14] = local_ip_address_lo;//source_low
packet[15] = ip_hi; //dest_high
packet[16] = ip_lo; //dest_low
number_of_bytes = total_length + 14;
 
//calculate checksum
reset_checksum();
for(i=7; i<=16; i++){
add_checksum(packet[i]);
}
packet[12] = check_checksum();
 
//enforce minimum ethernet frame size
if(number_of_bytes < 64){
number_of_bytes = 64;
}
 
//send packet over ethernet
put_ethernet_packet(
packet, //packet
number_of_bytes, //number_of_bytes
arp_mac_0[arp_cache], //destination mac address
arp_mac_1[arp_cache], //
arp_mac_2[arp_cache], //
0x0800); //protocol IPv4
}
 
unsigned get_ip_packet(unsigned packet[]){
unsigned ip_payload;
unsigned total_length;
unsigned header_length;
unsigned payload_start;
unsigned payload_length;
unsigned i, from, to;
unsigned payload_end;
 
number_of_bytes = get_ethernet_packet(packet);
 
if(number_of_bytes == 0) return 0;
if(packet[6] != 0x0800) return 0;
if(packet[15] != local_ip_address_hi) return 0;
if(packet[16] != local_ip_address_lo) return 0;
if((packet[11] & 0xff) == 1){//ICMP
header_length = ((packet[7] >> 8) & 0xf) << 1; //in words
payload_start = header_length + 7; //in words
total_length = packet[8]; //in bytes
payload_length = ((total_length+1) >> 1) - header_length; //in words
payload_end = payload_start + payload_length - 1; //in words
 
if(packet[payload_start] == 0x0800){//ping request
 
//copy icmp packet to response
to = 19;//assume that 17 and 18 are 0
reset_checksum();
for(from=payload_start+2; from<=payload_end; from++){
i = packet[from];
add_checksum(i);
tx_packet[to] = i;
to++;
}
tx_packet[17] = 0;//ping response
tx_packet[18] = check_checksum();
 
//send ping response
put_ip_packet(
tx_packet,
total_length,
1,//icmp
packet[13], //remote ip
packet[14] //remote ip
);
}
return 0;
}
if((packet[11] & 0xff) != 6) return 0;//TCP
return number_of_bytes;
}
 
////////////////////////////////////////////////////////////////////////////////
// Transport Layer - TCP
//
 
unsigned remote_ip_hi, remote_ip_lo;
 
unsigned tx_source=0;
unsigned tx_dest=0;
unsigned tx_seq[2];
unsigned next_tx_seq[2];
unsigned tx_ack[2];
unsigned tx_window=1460; //ethernet MTU - 40 bytes for TCP/IP header
 
unsigned tx_fin_flag=0;
unsigned tx_syn_flag=0;
unsigned tx_rst_flag=0;
unsigned tx_psh_flag=0;
unsigned tx_ack_flag=0;
unsigned tx_urg_flag=0;
 
unsigned rx_source=0;
unsigned rx_dest=0;
unsigned rx_seq[2];
unsigned rx_ack[2];
unsigned rx_window=0;
 
unsigned rx_fin_flag=0;
unsigned rx_syn_flag=0;
unsigned rx_rst_flag=0;
unsigned rx_psh_flag=0;
unsigned rx_ack_flag=0;
unsigned rx_urg_flag=0;
 
void put_tcp_packet(unsigned tx_packet [], unsigned tx_length){
 
unsigned payload_start = 17;
unsigned packet_length;
unsigned index;
 
//encode TCP header
tx_packet[payload_start + 0] = tx_source;
tx_packet[payload_start + 1] = tx_dest;
tx_packet[payload_start + 2] = tx_seq[1];
tx_packet[payload_start + 3] = tx_seq[0];
tx_packet[payload_start + 4] = tx_ack[1];
tx_packet[payload_start + 5] = tx_ack[0];
tx_packet[payload_start + 6] = 0x5000; //5 long words
tx_packet[payload_start + 7] = tx_window;
tx_packet[payload_start + 8] = 0;
tx_packet[payload_start + 9] = 0;
 
//encode flags
if(tx_fin_flag) tx_packet[payload_start + 6] |= 0x01;
if(tx_syn_flag) tx_packet[payload_start + 6] |= 0x02;
if(tx_rst_flag) tx_packet[payload_start + 6] |= 0x04;
if(tx_psh_flag) tx_packet[payload_start + 6] |= 0x08;
if(tx_ack_flag) tx_packet[payload_start + 6] |= 0x10;
if(tx_urg_flag) tx_packet[payload_start + 6] |= 0x20;
 
//calculate checksum
//length of payload + header + pseudo_header in words
reset_checksum();
add_checksum(local_ip_address_hi);
add_checksum(local_ip_address_lo);
add_checksum(remote_ip_hi);
add_checksum(remote_ip_lo);
add_checksum(0x0006);
add_checksum(tx_length+20);//tcp_header + tcp_payload in bytes
 
packet_length = (tx_length + 20 + 1) >> 1;
index = payload_start;
for(i=0; i<packet_length; i++){
add_checksum(tx_packet[index]);
index++;
}
tx_packet[payload_start + 8] = check_checksum();
 
put_ip_packet(
tx_packet,
tx_length + 40,
6,//tcp
remote_ip_hi, //remote ip
remote_ip_lo //remote ip
);
}
 
unsigned rx_length, rx_start;
 
unsigned get_tcp_packet(unsigned rx_packet []){
 
unsigned number_of_bytes, header_length, payload_start, total_length, payload_length, payload_end, tcp_header_length;
 
number_of_bytes = get_ip_packet(rx_packet);
 
//decode lengths from the IP header
header_length = ((rx_packet[7] >> 8) & 0xf) << 1; //in words
payload_start = header_length + 7; //in words
 
total_length = rx_packet[8]; //in bytes
payload_length = total_length - (header_length << 1); //in bytes
tcp_header_length = ((rx_packet[payload_start + 6] & 0xf000u)>>10); //in bytes
rx_length = payload_length - tcp_header_length; //in bytes
rx_start = payload_start + (tcp_header_length >> 1); //in words
 
//decode TCP header
rx_source = rx_packet[payload_start + 0];
rx_dest = rx_packet[payload_start + 1];
rx_seq[1] = rx_packet[payload_start + 2];
rx_seq[0] = rx_packet[payload_start + 3];
rx_ack[1] = rx_packet[payload_start + 4];
rx_ack[0] = rx_packet[payload_start + 5];
rx_window = rx_packet[payload_start + 7];
 
//decode flags
rx_fin_flag = rx_packet[payload_start + 6] & 0x01;
rx_syn_flag = rx_packet[payload_start + 6] & 0x02;
rx_rst_flag = rx_packet[payload_start + 6] & 0x04;
rx_psh_flag = rx_packet[payload_start + 6] & 0x08;
rx_ack_flag = rx_packet[payload_start + 6] & 0x10;
rx_urg_flag = rx_packet[payload_start + 6] & 0x20;
 
return number_of_bytes;
}
 
void application_put_data(unsigned packet[], unsigned start, unsigned length){
unsigned i, index;
 
index = start;
put_socket(length);
for(i=0; i<length; i+=2){
put_socket(packet[index]);
index++;
}
}
 
unsigned application_get_data(unsigned packet[], unsigned start){
unsigned i, index, length;
 
if(!ready_socket()){
return 0;
}
 
index = start;
length = get_socket();
for(i=0; i<length; i+=2){
packet[index] = get_socket();
index++;
}
return length;
}
 
void server()
{
unsigned rx_packet[1024];
unsigned tx_packet[1024];
unsigned tx_start = 27;
 
unsigned new_rx_data = 0;
unsigned new_tx_data = 0;
unsigned tx_length;
unsigned timeout;
unsigned resend_wait;
unsigned bytes;
unsigned last_state;
unsigned new_rx_data;
 
unsigned listen = 0;
unsigned open = 1;
unsigned send = 2;
unsigned wait_acknowledge = 3;
unsigned close = 4;
unsigned state = listen;
 
tx_seq[0] = 0;
tx_seq[1] = 0;
 
while(1){
 
if(timeout){
timeout--;
} else {
timeout = 120; //2 mins @100 MHz
state = listen;
tx_syn_flag = 0;
tx_fin_flag = 0;
tx_ack_flag = 0;
tx_rst_flag = 1;
put_tcp_packet(tx_packet, 0);//send reset packet
}
 
// (optionaly) send something
switch(state){
case 0:
tx_rst_flag = 0;
tx_syn_flag = 0;
tx_fin_flag = 0;
tx_ack_flag = 0;
break;
case 1:
// set remote ip/port
remote_ip_hi = rx_packet[13];
remote_ip_lo = rx_packet[14];
tx_dest = rx_source;
tx_source = local_port;
// send syn_ack
calc_ack(tx_ack, rx_seq, 1);
tx_syn_flag = 1;
tx_ack_flag = 1;
put_tcp_packet(tx_packet, 0);
break;
case 2:
// application -> tcp
tx_length = application_get_data(tx_packet, tx_start);
tx_seq[0] = next_tx_seq[0];
tx_seq[1] = next_tx_seq[1];
calc_ack(next_tx_seq, tx_seq, tx_length);
tx_syn_flag = 0;
tx_ack_flag = 1;
put_tcp_packet(tx_packet, tx_length);
break;
case 3:
// resend until acknowledge recieved
put_tcp_packet(tx_packet, tx_length);
break;
case 4:
// send fin ack
tx_fin_flag = 1;
tx_ack_flag = 1;
calc_ack(tx_ack, rx_seq, 1);
put_tcp_packet(tx_packet, 0);
break;
}
 
// repeatedly check for responses
for(resend_wait = 10000; resend_wait; resend_wait--){ //1 second @ 100MHz
bytes = get_tcp_packet(rx_packet);
if(bytes && (rx_dest == local_port)){
//Once connection is established ignore other connection attempts
if(state != listen && rx_source != tx_dest) continue;
new_rx_data = 0;
last_state = state;
switch(state){
 
// If a syn packet is recieved, wait for an ack
case 0:
if(rx_syn_flag) state = open;
else{
tx_rst_flag = 1;
put_tcp_packet(tx_packet, 0);//send reset packet
}
break;
 
// If an ack is recieved the connection is established
case 1:
if(rx_ack_flag){
tx_seq[1] = rx_ack[1];
tx_seq[0] = rx_ack[0];
next_tx_seq[1] = rx_ack[1];
next_tx_seq[0] = rx_ack[0];
state = send;
}
break;
 
// Send some data
case 2:
new_rx_data = calc_ack(tx_ack, rx_seq, rx_length);
if(rx_fin_flag){
state = close;
} else if( tx_length ){
state = wait_acknowledge;
}
break;
 
// Wait until data is acknowledged before sending some more.
case 3:
 
new_rx_data = calc_ack(tx_ack, rx_seq, rx_length);
if(rx_fin_flag){
state = close;
} else if( rx_ack_flag &&
(next_tx_seq[1] == rx_ack[1]) &&
(next_tx_seq[0] == rx_ack[0])){
state = send;
}
 
break;
 
// wait for fin/ack.
case 4:
if(rx_ack_flag) state = listen;
break;
}
 
if(rx_rst_flag) state = listen;
 
// Transfer any new data to the application
if(new_rx_data){
application_put_data(rx_packet, rx_start, rx_length);
//Ack can go in next transmission.
if(state == last_state) put_tcp_packet(tx_packet, tx_length);
}
 
if(state == send && ready_socket()){
break;
}
 
if(state != last_state){
timeout = 120;
break;
}
 
} else {
wait_clocks(10000);//100 us @100 MHz
}
}
}
}
/source/atlys.vhd
0,0 → 1,706
--------------------------------------------------------------------------------
---
--- CHIPS - 2.0 Simple Web App Demo
---
--- :Author: Jonathan P Dawson
--- :Date: 17/10/2013
--- :email: chips@jondawson.org.uk
--- :license: MIT
--- :Copyright: Copyright (C) Jonathan P Dawson 2013
---
--- A Serial Input Component
---
--------------------------------------------------------------------------------
---
--- +--------------+
--- | CLOCK TREE |
--- +--------------+
--- | >-- CLK1 (50MHz) ---> CLK
--- CLK_IN >--> |
--- | >-- CLK2 (100MHz)
--- | | +-------+
--- | +-- CLK3 (125MHz) ->+ ODDR2 +-->[GTXCLK]
--- | | | |
--- | +-- CLK3_N (125MHZ) ->+ |
--- | | +-------+
--- RST >-----> >-- CLK4 (200MHz)
--- | |
--- | |
--- | | CLK >--+--------+
--- | | | |
--- | | +--v-+ +--v-+
--- | | | | | |
--- | LOCKED >------> >---> >-------> INTERNAL_RESET
--- | | | | | |
--- +--------------+ +----+ +----+
---
--- +-------------+ +--------------+
--- | SERVER | | USER DESIGN |
--- +-------------+ +--------------+
--- | | | |
--- | >-----> <-------< SWITCHES
--- | | | |
--- | <-----< >-------> LEDS
--- | | | |
--- | | | <-------< BUTTONS
--- | | | |
--- | | +----^----v----+
--- | | | |
--- | | +----^----v----+
--- | | | UART |
--- | | +--------------+
--- | | | >-------> RS232-TX
--- | | | |
--- +---v-----^---+ | <-------< RS232-RX
--- | | +--------------+
--- +---v-----^---+
--- | ETHERNET |
--- | MAC |
--- +-------------+
--- | +------> [PHY_RESET]
--- | |
---[RXCLK] ----->+ +------> [TXCLK]
--- | |
--- 125MHZ ----->+ +------> open
--- | |
--- [RXD] ----->+ +------> [TXD]
--- | |
--- [RXDV] ----->+ +------> [TXEN]
--- | |
--- [RXER] ----->+ +------> [TXER]
--- | |
--- | |
--- +-------------+
---
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library unisim;
use unisim.vcomponents.all;
 
entity ATLYS is
port(
CLK_IN : in std_logic;
RST : in std_logic;
 
--PHY INTERFACE
TX : out std_logic;
RX : in std_logic;
PHY_RESET : out std_logic;
RXDV : in std_logic;
RXER : in std_logic;
RXCLK : in std_logic;
RXD : in std_logic_vector(7 downto 0);
TXCLK : in std_logic;
GTXCLK : out std_logic;
TXD : out std_logic_vector(7 downto 0);
TXEN : out std_logic;
TXER : out std_logic;
 
--LEDS
GPIO_LEDS : out std_logic_vector(7 downto 0);
GPIO_SWITCHES : in std_logic_vector(7 downto 0);
GPIO_BUTTONS : in std_logic_vector(3 downto 0);
 
--RS232 INTERFACE
RS232_RX : in std_logic;
RS232_TX : out std_logic
);
end entity ATLYS;
 
architecture RTL of ATLYS is
 
component gigabit_ethernet is
port(
CLK : in std_logic;
RST : in std_logic;
 
--Ethernet Clock
CLK_125_MHZ : in std_logic;
 
--GMII IF
GTXCLK : out std_logic;
TXCLK : in std_logic;
TXER : out std_logic;
TXEN : out std_logic;
TXD : out std_logic_vector(7 downto 0);
PHY_RESET : out std_logic;
RXCLK : in std_logic;
RXER : in std_logic;
RXDV : in std_logic;
RXD : in std_logic_vector(7 downto 0);
 
--RX STREAM
TX : in std_logic_vector(15 downto 0);
TX_STB : in std_logic;
TX_ACK : out std_logic;
 
--RX STREAM
RX : out std_logic_vector(15 downto 0);
RX_STB : out std_logic;
RX_ACK : in std_logic
);
end component gigabit_ethernet;
 
component SERVER is
port(
CLK : in std_logic;
RST : in std_logic;
--ETH RX STREAM
INPUT_ETH_RX : in std_logic_vector(15 downto 0);
INPUT_ETH_RX_STB : in std_logic;
INPUT_ETH_RX_ACK : out std_logic;
 
--ETH TX STREAM
output_eth_tx : out std_logic_vector(15 downto 0);
OUTPUT_ETH_TX_STB : out std_logic;
OUTPUT_ETH_TX_ACK : in std_logic;
 
--SOCKET RX STREAM
INPUT_SOCKET : in std_logic_vector(15 downto 0);
INPUT_SOCKET_STB : in std_logic;
INPUT_SOCKET_ACK : out std_logic;
 
--SOCKET TX STREAM
OUTPUT_SOCKET : out std_logic_vector(15 downto 0);
OUTPUT_SOCKET_STB : out std_logic;
OUTPUT_SOCKET_ACK : in std_logic
 
);
end component;
 
component USER_DESIGN is
port(
CLK : in std_logic;
RST : in std_logic;
OUTPUT_LEDS : out std_logic_vector(15 downto 0);
OUTPUT_LEDS_STB : out std_logic;
OUTPUT_LEDS_ACK : in std_logic;
 
INPUT_SWITCHES : in std_logic_vector(15 downto 0);
INPUT_SWITCHES_STB : in std_logic;
INPUT_SWITCHES_ACK : out std_logic;
 
INPUT_BUTTONS : in std_logic_vector(15 downto 0);
INPUT_BUTTONS_STB : in std_logic;
INPUT_BUTTONS_ACK : out std_logic;
 
--SOCKET RX STREAM
INPUT_SOCKET : in std_logic_vector(15 downto 0);
INPUT_SOCKET_STB : in std_logic;
INPUT_SOCKET_ACK : out std_logic;
 
--SOCKET TX STREAM
OUTPUT_SOCKET : out std_logic_vector(15 downto 0);
OUTPUT_SOCKET_STB : out std_logic;
OUTPUT_SOCKET_ACK : in std_logic;
 
--RS232 RX STREAM
INPUT_RS232_RX : in std_logic_vector(15 downto 0);
INPUT_RS232_RX_STB : in std_logic;
INPUT_RS232_RX_ACK : out std_logic;
 
--RS232 TX STREAM
OUTPUT_RS232_TX : out std_logic_vector(15 downto 0);
OUTPUT_RS232_TX_STB : out std_logic;
OUTPUT_RS232_TX_ACK : in std_logic
 
 
);
end component;
 
component SERIAL_INPUT is
generic(
CLOCK_FREQUENCY : integer;
BAUD_RATE : integer
);
port(
CLK : in std_logic;
RST : in std_logic;
RX : in std_logic;
OUT1 : out std_logic_vector(7 downto 0);
OUT1_STB : out std_logic;
OUT1_ACK : in std_logic
);
end component SERIAL_INPUT;
 
component serial_output is
generic(
CLOCK_FREQUENCY : integer;
BAUD_RATE : integer
);
port(
CLK : in std_logic;
RST : in std_logic;
TX : out std_logic;
IN1 : in std_logic_vector(7 downto 0);
IN1_STB : in std_logic;
IN1_ACK : out std_logic
);
end component serial_output;
 
--chips signals
signal CLK : std_logic;
signal RST_INV : std_logic;
 
--clock tree signals
signal clkin1 : std_logic;
-- Output clock buffering
signal clkfb : std_logic;
signal clk0 : std_logic;
signal clk2x : std_logic;
signal clkfx : std_logic;
signal clkfx180 : std_logic;
signal clkdv : std_logic;
signal clkfbout : std_logic;
signal locked_internal : std_logic;
signal status_internal : std_logic_vector(7 downto 0);
signal CLK_OUT1 : std_logic;
signal CLK_OUT2 : std_logic;
signal CLK_OUT3 : std_logic;
signal CLK_OUT3_N : std_logic;
signal CLK_OUT4 : std_logic;
signal NOT_LOCKED : std_logic;
signal INTERNAL_RST : std_logic;
signal RXD1 : std_logic;
signal TX_LOCKED : std_logic;
signal INTERNAL_RXCLK : std_logic;
signal INTERNAL_RXCLK_BUF: std_logic;
signal RXCLK_BUF : std_logic;
 
signal INTERNAL_TXD : std_logic_vector(7 downto 0);
signal INTERNAL_TXEN : std_logic;
signal INTERNAL_TXER : std_logic;
signal OUTPUT_LEDS : std_logic_vector(15 downto 0);
signal OUTPUT_LEDS_STB : std_logic;
signal OUTPUT_LEDS_ACK : std_logic;
 
signal INPUT_SWITCHES : std_logic_vector(15 downto 0);
signal INPUT_SWITCHES_STB : std_logic;
signal INPUT_SWITCHES_ACK : std_logic;
signal GPIO_SWITCHES_D : std_logic_vector(7 downto 0);
 
signal INPUT_BUTTONS : std_logic_vector(15 downto 0);
signal INPUT_BUTTONS_STB : std_logic;
signal INPUT_BUTTONS_ACK : std_logic;
signal GPIO_BUTTONS_D : std_logic_vector(3 downto 0);
--ETH RX STREAM
signal ETH_RX : std_logic_vector(15 downto 0);
signal ETH_RX_STB : std_logic;
signal ETH_RX_ACK : std_logic;
 
--ETH TX STREAM
signal ETH_TX : std_logic_vector(15 downto 0);
signal ETH_TX_STB : std_logic;
signal ETH_TX_ACK : std_logic;
 
--RS232 RX STREAM
signal INPUT_RS232_RX : std_logic_vector(15 downto 0);
signal INPUT_RS232_RX_STB : std_logic;
signal INPUT_RS232_RX_ACK : std_logic;
 
--RS232 TX STREAM
signal OUTPUT_RS232_TX : std_logic_vector(15 downto 0);
signal OUTPUT_RS232_TX_STB : std_logic;
signal OUTPUT_RS232_TX_ACK : std_logic;
 
--SOCKET RX STREAM
signal INPUT_SOCKET : std_logic_vector(15 downto 0);
signal INPUT_SOCKET_STB : std_logic;
signal INPUT_SOCKET_ACK : std_logic;
 
--SOCKET TX STREAM
signal OUTPUT_SOCKET : std_logic_vector(15 downto 0);
signal OUTPUT_SOCKET_STB : std_logic;
signal OUTPUT_SOCKET_ACK : std_logic;
 
begin
 
gigabit_ethernet_inst_1 : gigabit_ethernet port map(
CLK => CLK,
RST => INTERNAL_RST,
 
--Ethernet Clock
CLK_125_MHZ => CLK_OUT3,
 
--GMII IF
GTXCLK => open,
TXCLK => TXCLK,
TXER => INTERNAL_TXER,
TXEN => INTERNAL_TXEN,
TXD => INTERNAL_TXD,
PHY_RESET => PHY_RESET,
RXCLK => INTERNAL_RXCLK,
RXER => RXER,
RXDV => RXDV,
RXD => RXD,
 
--RX STREAM
TX => ETH_TX,
TX_STB => ETH_TX_STB,
TX_ACK => ETH_TX_ACK,
 
--RX STREAM
RX => ETH_RX,
RX_STB => ETH_RX_STB,
RX_ACK => ETH_RX_ACK
);
 
SERVER_INST_1 : SERVER port map(
CLK => CLK,
RST => INTERNAL_RST,
--ETH RX STREAM
INPUT_ETH_RX => ETH_RX,
INPUT_ETH_RX_STB => ETH_RX_STB,
INPUT_ETH_RX_ACK => ETH_RX_ACK,
 
--ETH TX STREAM
OUTPUT_ETH_TX => ETH_TX,
OUTPUT_ETH_TX_STB => ETH_TX_STB,
OUTPUT_ETH_TX_ACK => ETH_TX_ACK,
 
--SOCKET STREAM
INPUT_SOCKET => INPUT_SOCKET,
INPUT_SOCKET_STB => INPUT_SOCKET_STB,
INPUT_SOCKET_ACK => INPUT_SOCKET_ACK,
 
--SOCKET STREAM
OUTPUT_SOCKET => OUTPUT_SOCKET,
OUTPUT_SOCKET_STB => OUTPUT_SOCKET_STB,
OUTPUT_SOCKET_ACK => OUTPUT_SOCKET_ACK
 
);
 
USER_DESIGN_INST_1 : USER_DESIGN port map(
CLK => CLK,
RST => INTERNAL_RST,
OUTPUT_LEDS => OUTPUT_LEDS,
OUTPUT_LEDS_STB => OUTPUT_LEDS_STB,
OUTPUT_LEDS_ACK => OUTPUT_LEDS_ACK,
 
INPUT_SWITCHES => INPUT_SWITCHES,
INPUT_SWITCHES_STB => INPUT_SWITCHES_STB,
INPUT_SWITCHES_ACK => INPUT_SWITCHES_ACK,
 
INPUT_BUTTONS => INPUT_BUTTONS,
INPUT_BUTTONS_STB => INPUT_BUTTONS_STB,
INPUT_BUTTONS_ACK => INPUT_BUTTONS_ACK,
 
--RS232 RX STREAM
INPUT_RS232_RX => INPUT_RS232_RX,
INPUT_RS232_RX_STB => INPUT_RS232_RX_STB,
INPUT_RS232_RX_ACK => INPUT_RS232_RX_ACK,
 
--RS232 TX STREAM
OUTPUT_RS232_TX => OUTPUT_RS232_TX,
OUTPUT_RS232_TX_STB => OUTPUT_RS232_TX_STB,
OUTPUT_RS232_TX_ACK => OUTPUT_RS232_TX_ACK,
 
--SOCKET STREAM
INPUT_SOCKET => OUTPUT_SOCKET,
INPUT_SOCKET_STB => OUTPUT_SOCKET_STB,
INPUT_SOCKET_ACK => OUTPUT_SOCKET_ACK,
 
--SOCKET STREAM
OUTPUT_SOCKET => INPUT_SOCKET,
OUTPUT_SOCKET_STB => INPUT_SOCKET_STB,
OUTPUT_SOCKET_ACK => INPUT_SOCKET_ACK
 
);
 
SERIAL_OUTPUT_INST_1 : serial_output generic map(
CLOCK_FREQUENCY => 50000000,
BAUD_RATE => 115200
)port map(
CLK => CLK,
RST => INTERNAL_RST,
TX => RS232_TX,
IN1 => OUTPUT_RS232_TX(7 downto 0),
IN1_STB => OUTPUT_RS232_TX_STB,
IN1_ACK => OUTPUT_RS232_TX_ACK
);
 
SERIAL_INPUT_INST_1 : SERIAL_INPUT generic map(
CLOCK_FREQUENCY => 50000000,
BAUD_RATE => 115200
) port map (
CLK => CLK,
RST => INTERNAL_RST,
RX => RS232_RX,
OUT1 => INPUT_RS232_RX(7 downto 0),
OUT1_STB => INPUT_RS232_RX_STB,
OUT1_ACK => INPUT_RS232_RX_ACK
);
 
INPUT_RS232_RX(15 downto 8) <= (others => '0');
 
process
begin
wait until rising_edge(CLK);
NOT_LOCKED <= not LOCKED_INTERNAL;
INTERNAL_RST <= NOT_LOCKED;
if OUTPUT_LEDS_STB = '1' then
GPIO_LEDS <= OUTPUT_LEDS(7 downto 0);
end if;
OUTPUT_LEDS_ACK <= '1';
 
INPUT_SWITCHES_STB <= '1';
GPIO_SWITCHES_D <= GPIO_SWITCHES;
INPUT_SWITCHES(7 downto 0) <= GPIO_SWITCHES_D;
INPUT_SWITCHES(15 downto 8) <= (others => '0');
 
INPUT_BUTTONS_STB <= '1';
GPIO_BUTTONS_D <= GPIO_BUTTONS;
INPUT_BUTTONS(3 downto 0) <= GPIO_BUTTONS_D;
INPUT_BUTTONS(15 downto 4) <= (others => '0');
 
end process;
 
 
-------------------------
-- Output Output
-- Clock Freq (MHz)
-------------------------
-- CLK_OUT1 50.000
-- CLK_OUT2 100.000
-- CLK_OUT3 125.000
-- CLK_OUT4 200.000
 
----------------------------------
-- Input Clock Input Freq (MHz)
----------------------------------
-- primary 200.000
 
 
-- Input buffering
--------------------------------------
clkin1_buf : IBUFG
port map
(O => clkin1,
I => CLK_IN);
 
 
-- Clocking primitive
--------------------------------------
-- Instantiation of the DCM primitive
-- * Unused inputs are tied off
-- * Unused outputs are labeled unused
dcm_sp_inst: DCM_SP
generic map
(CLKDV_DIVIDE => 2.000,
CLKFX_DIVIDE => 4,
CLKFX_MULTIPLY => 5,
CLKIN_DIVIDE_BY_2 => FALSE,
CLKIN_PERIOD => 10.0,
CLKOUT_PHASE_SHIFT => "NONE",
CLK_FEEDBACK => "1X",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
PHASE_SHIFT => 0,
STARTUP_WAIT => FALSE)
port map
-- Input clock
(CLKIN => clkin1,
CLKFB => clkfb,
-- Output clocks
CLK0 => clk0,
CLK90 => open,
CLK180 => open,
CLK270 => open,
CLK2X => clk2x,
CLK2X180 => open,
CLKFX => clkfx,
CLKFX180 => clkfx180,
CLKDV => clkdv,
-- Ports for dynamic phase shift
PSCLK => '0',
PSEN => '0',
PSINCDEC => '0',
PSDONE => open,
-- Other control and status signals
LOCKED => TX_LOCKED,
STATUS => status_internal,
RST => RST_INV,
-- Unused pin, tie low
DSSEN => '0');
 
RST_INV <= not RST;
 
 
 
-- Output buffering
-------------------------------------
clkfb <= CLK_OUT2;
 
BUFG_INST1 : BUFG
port map
(O => CLK_OUT1,
I => clkdv);
 
BUFG_INST2 : BUFG
port map
(O => CLK_OUT2,
I => clk0);
 
BUFG_INST3 : BUFG
port map
(O => CLK_OUT3,
I => clkfx);
BUFG_INST4 : BUFG
port map
(O => CLK_OUT3_N,
I => clkfx180);
 
BUFG_INST5 : BUFG
port map
(O => CLK_OUT4,
I => clk2x);
ODDR2_INST1 : ODDR2
generic map(
DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1"
INIT => '0', -- Sets initial state of the Q output to '0' or '1'
SRTYPE => "SYNC"
) port map (
Q => GTXCLK, -- 1-bit output data
C0 => CLK_OUT3, -- 1-bit clock input
C1 => CLK_OUT3_N, -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => '1', -- 1-bit data input (associated with C0)
D1 => '0', -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
);
 
-- Input buffering
--------------------------------------
BUFG_INST6 : IBUFG
port map
(O => RXCLK_BUF,
I => RXCLK);
 
-- DCM
--------------------------------------
dcm_sp_inst2: DCM_SP
generic map
(CLKDV_DIVIDE => 2.000,
CLKFX_DIVIDE => 4,
CLKFX_MULTIPLY => 5,
CLKIN_DIVIDE_BY_2 => FALSE,
CLKIN_PERIOD => 8.0,
CLKOUT_PHASE_SHIFT => "FIXED",
CLK_FEEDBACK => "1X",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
PHASE_SHIFT => 14,
STARTUP_WAIT => FALSE)
port map
-- Input clock
(CLKIN => RXCLK_BUF,
CLKFB => INTERNAL_RXCLK,
-- Output clocks
CLK0 => INTERNAL_RXCLK_BUF,
CLK90 => open,
CLK180 => open,
CLK270 => open,
CLK2X => open,
CLK2X180 => open,
CLKFX => open,
CLKFX180 => open,
CLKDV => open,
-- Ports for dynamic phase shift
PSCLK => '0',
PSEN => '0',
PSINCDEC => '0',
PSDONE => open,
-- Other control and status signals
LOCKED => open,
STATUS => open,
RST => RST_INV,
-- Unused pin, tie low
DSSEN => '0');
 
-- Output buffering
--------------------------------------
BUFG_INST7 : BUFG
port map
(O => INTERNAL_RXCLK,
I => INTERNAL_RXCLK_BUF);
 
LOCKED_INTERNAL <= TX_LOCKED;
 
-- Use ODDRs for clock/data forwarding
--------------------------------------
ODDR2_INST2_GENERATE : for I in 0 to 7 generate
ODDR2_INST2 : ODDR2
generic map(
DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1"
INIT => '0', -- Sets initial state of the Q output to '0' or '1'
SRTYPE => "SYNC"
) port map (
Q => TXD(I), -- 1-bit output data
C0 => CLK_OUT3, -- 1-bit clock input
C1 => CLK_OUT3_N, -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => INTERNAL_TXD(I), -- 1-bit data input (associated with C0)
D1 => INTERNAL_TXD(I), -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
);
end generate;
 
ODDR2_INST3 : ODDR2
generic map(
DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1"
INIT => '0', -- Sets initial state of the Q output to '0' or '1'
SRTYPE => "SYNC"
) port map (
Q => TXEN, -- 1-bit output data
C0 => CLK_OUT3, -- 1-bit clock input
C1 => CLK_OUT3_N, -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => INTERNAL_TXEN, -- 1-bit data input (associated with C0)
D1 => INTERNAL_TXEN, -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
);
 
ODDR2_INST4 : ODDR2
generic map(
DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1"
INIT => '0', -- Sets initial state of the Q output to '0' or '1'
SRTYPE => "SYNC"
) port map (
Q => TXER, -- 1-bit output data
C0 => CLK_OUT3, -- 1-bit clock input
C1 => CLK_OUT3_N, -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => INTERNAL_TXER, -- 1-bit data input (associated with C0)
D1 => INTERNAL_TXER, -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
);
 
 
-- Chips CLK frequency selection
-------------------------------------
 
CLK <= CLK_OUT1; --50 MHz
--CLK <= CLK_OUT2; --100 MHz
--CLK <= CLK_OUT3; --125 MHz
--CLK <= CLK_OUT4; --200 MHz
 
end architecture RTL;
/atlys.py
0,0 → 1,706
link scripts/atlys.py
atlys.py Property changes : Added: svn:special ## -0,0 +1 ## +* \ No newline at end of property Index: README.rst =================================================================== --- README.rst (nonexistent) +++ README.rst (revision 2) @@ -0,0 +1,97 @@ +Chips-2.0 Demo for ATLYS Development Card +========================================= + +:Author: Jonathan P Dawson +:Date: 2013-10-15 +:email: chips@jondawson.org.uk + + +This project is intended to demonstrate the capabilities of the `Chips-2.0 `_ development environment. The project is targets the Xilinx Spartan 6 device, and more specifically, the Digilent ATLYS development platform. The demo implements a TCP/IP socket interface, and a simple web application. So far the demonstration has been tested on a Ubuntu Linux only. + +Dependencies +============ + +You will need: + ++ Xilinx ISE 12.0 or later (webpack edition is free) ++ Python 2.7 or later (but not Python 3) ++ Chips-2.0 (Included) ++ Digilent `ATLYS `_ Spartan 6 Development Kit. ++ Digilent ADEPT2 `utility `_ ++ git + +Install +======= + +Clone the git the repository with git:: + + $ git clone git@github.com:dawsonjon/Chips-Demo.git + $ cd Chips-Demo + $ git submodule init + $ git submodule update + +Chips Compile +============= + +To compile the c code in chips, issue the following command in the project folder:: + + $ ./atlys.py compile + +Build in ISE +============ + +Edit the Xilinx variable in the scripts/user_settings to point to the Xilinx ISE install directory. Then build the design using the following command:: + + $ ./atlys.py build + +Download to ATLYS +================= + +Power up the ATLYS, and connect the JTAG USB cable to your PC. Run the download command:: + + $ ./atlys.py download + +You can complete all three steps in one go using the *all* option:: + + $ ./atlys.py all + +Setup and Test +============== + +:: + + +----------------+ +----------------+ + | PC | | Digilent ATLYS | + | | POWER =======>o | + | | | | + | USB o<===============>o JTAG USB | + | | | | + | ETH0 o<===============>o ETHERNET | + | | | | + | 192.168.1.0 | | 192.168.1.1 | + +----------------+ +----------------+ + +.. + +Connect the Ethernet port to ATLYS, using a crossed over Ethernet cable (which comes with the development kit). + +Using the script, configure Ethernet port with IP address 192.168.1.0 and subnet mask 255.255.255.0. Turn off TCP Window Scaling and TCP time stamps:: + + $ ./configure_network + +Verify connection using ping command:: + + $ ping 192.168.1.1 + PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. + 64 bytes from 192.168.1.1: icmp_req=2 ttl=255 time=0.207 ms + 64 bytes from 192.168.1.1: icmp_req=3 ttl=255 time=0.263 ms + 64 bytes from 192.168.1.1: icmp_req=4 ttl=255 time=0.124 ms + 64 bytes from 192.168.1.1: icmp_req=5 ttl=255 time=0.185 ms + 64 bytes from 192.168.1.1: icmp_req=6 ttl=255 time=0.275 ms + --- 192.168.1.1 ping statistics --- + 6 packets transmitted, 5 received, 16% packet loss, time 5001ms + rtt min/avg/max/mdev = 0.124/0.210/0.275/0.057 ms + +Connect to 192.168.1.1 using your favourite browser. + +.. image:: https://raw.github.com/dawsonjon/Chips-Demo/master/images/screenshot.png Index: images/screenshot.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: images/screenshot.png =================================================================== --- images/screenshot.png (nonexistent) +++ images/screenshot.png (revision 2)
images/screenshot.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: README.pdf =================================================================== --- README.pdf (nonexistent) +++ README.pdf (revision 2) @@ -0,0 +1,883 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +% 'BasicFonts': class PDFDictionary +1 0 obj +% The standard fonts dictionary +<< /F1 2 0 R + /F2 3 0 R + /F3 8 0 R + /F4 10 0 R >> +endobj +% 'F1': class PDFType1Font +2 0 obj +% Font Helvetica +<< /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font >> +endobj +% 'F2': class PDFType1Font +3 0 obj +% Font Helvetica-Bold +<< /BaseFont /Helvetica-Bold + /Encoding /WinAnsiEncoding + /Name /F2 + /Subtype /Type1 + /Type /Font >> +endobj +% 'Annot.NUMBER1': class PDFDictionary +4 0 obj +<< /A << /S /URI + /Type /Action + /URI (mailto:chips@jondawson.org.uk) >> + /Border [ 0 + 0 + 0 ] + /Rect [ 153.7323 + 690.7736 + 526.5827 + 702.7736 ] + /Subtype /Link + /Type /Annot >> +endobj +% 'Annot.NUMBER2': class PDFDictionary +5 0 obj +<< /A << /S /URI + /Type /Action + /URI (https://github.com/dawsonjon/Chips-2.0) >> + /Border [ 0 + 0 + 0 ] + /Rect [ 345.785 + 669.7736 + 392.4843 + 681.7736 ] + /Subtype /Link + /Type /Annot >> +endobj +% 'Annot.NUMBER3': class PDFDictionary +6 0 obj +<< /A << /S /URI + /Type /Action + /URI (http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,836&Prod=ATLYS&CFID=3188339&CFTOKEN=15014968) >> + /Border [ 0 + 0 + 0 ] + /Rect [ 121.8129 + 507.7736 + 156.2729 + 519.7736 ] + /Subtype /Link + /Type /Annot >> +endobj +% 'Annot.NUMBER4': class PDFDictionary +7 0 obj +<< /A << /S /URI + /Type /Action + /URI (http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,66,828&Prod=ADEPT2) >> + /Border [ 0 + 0 + 0 ] + /Rect [ 163.4929 + 489.7736 + 186.2729 + 501.7736 ] + /Subtype /Link + /Type /Annot >> +endobj +% 'F3': class PDFType1Font +8 0 obj +% Font Courier +<< /BaseFont /Courier + /Encoding /WinAnsiEncoding + /Name /F3 + /Subtype /Type1 + /Type /Font >> +endobj +% 'Page1': class PDFPage +9 0 obj +% Page dictionary +<< /Annots [ 4 0 R + 5 0 R + 6 0 R + 7 0 R ] + /Contents 25 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 24 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'F4': class PDFType1Font +10 0 obj +% Font Helvetica-Oblique +<< /BaseFont /Helvetica-Oblique + /Encoding /WinAnsiEncoding + /Name /F4 + /Subtype /Type1 + /Type /Font >> +endobj +% 'FormXob.dff977657d895d2e15b12a22f3b5ae1c': class PDFImageXObject +11 0 obj +<< /BitsPerComponent 8 + /ColorSpace /DeviceRGB + /Filter [ /ASCII85Decode + /FlateDecode ] + /Height 550 + /Length 60785 + /SMask 12 0 R + /Subtype /Image + /Type /XObject + /Width 883 >> +stream +Gb",k#?VZ&+30;tW&Rs^lMtSJg0p?ADjPU!"8CXc`@W\V[g99NWJI2q/qsb(+L4GhH\MYoa9"]L+pn$omk08Y!eaR\rI(:+_aA=SpYO^Fn)O<%*M7]\zzz!!)LCctU;qQ5No:\DOf9j4\)A1OGJgg8@<-D!9=i%s`DE>WjjIO!_-j&aLH#CmGRqXO.4klT4\,Q+KfF>]f`0E5-(-Cl@0%4Z2OXe)Bm)4"m7Yr.3O'f?UaLM[[d2J?qI&gOOCG"?gelU7Rj>^utrMfWTV4nkHh7f>dl*r=F]t93I#p[.B?.C@$bL"qs9e@?g?o>H)GLC0mO*s(3AuTi.Pekr)IEIjXbP&Fh>"bQ#B_D=HocX^@WudVp:@4E+Z?sjqoH(bhLIq/i)P_8E\dY.96a;@M@s`@r"98E%!.]P.h8UAEgi,EfoT(`EFGG8:rIgSS2U<8rWD,;Dkmtd80[/\FFM_R`e*o5<="G*rD@<`!)E;NIM;c<#^Q'?5eX0_,mCdK#b&N&"SJ8Q/eSilBMrTS/Y$=!bC\N,_;HWqA^Qu!,0Os,7/N-ZM[uKXP.$b5m/mGFVBrJ1n!M?F-:F`Aq9QQ9D'jIH4?P!"-s0-L$9jKB>9Q&YZ]*t7=@-1h2HolYmnBjJdD6\&&2-W&MZ^OBOUXG0&FRsH.5;&LVnEOk&!=pDWbPK[Vs!+T4p0kXY/N"G'6'Wg"=GVmFU'*K:Rb!4R[Z0^+Nh0)VW(UXZq']`l\%.`UR7*X*`S^oUTgXE.6&5SZ>EJd-'jb:0-[MFfo@-.d8Zr^U(92oIk"FfP-HHJ^[j&2sd_8cHaGie.G=k>5`**FLL$'[A$b5RWmKER,/YPG62sOguG`eH>4rP,*g^**kTnKfjnPFfh(G,Zgb'fl+)GR<"rHLP\L0-bJE_i'NJdHq.Q]oO8iX(:$miTf]/=cG0WTh+$Sr[om/./1\5D4O>p'[RmqP&YE%=$mW!8:2/HGRz!;Ksd3+SGb]CVVN"&sA?Frn3^]\U;/A`L+crMCR?4ulu*&Bh9.Qs8=8h>HHO:HN[^0m\t]or2LI)B5jHnu\%VmG:(ASS*8oB`)K]B\Q2+fH-N7G@,Ogr-pf0Ce[u+(uG9#SaZ2pT!pkn?mtH'*I@[uf@k%@[97\:1XXkObd-2%o#_Gj-6KP$1Ank5[:OIu2UCIZRNHj!r+s56>MEFJF]6%+XY4<,Yr,mlkY#(]kEoH-=B\h]g7CNOB\S,GFm@$^Eic%E[ap1?GH#XO<*)HaLE/:]HcPlBYHC9[nEb`$m*Bf*F26!%BD28Z[h2L%r:NN81S^R,lSDu8n_KE+C3J*tJ(3hXr]h`pRXHRP1HW"apL[:H#cAb%NaFe\UX@WCZ+$J(EiWh&;IZMhZGlN:RQr9Dt>6HJ1f3dcSIE=8^KNVD'%%J$[(Xi/fZ,k&31=Y\$5:3X/pbBW)/>CZ?RJKseL>[Go8)_uKDp3b6su9acI=h0%AE"/aiQY-lUNJNC/O8DOBE:r=L_<\)]3zJ<-:^*BR#c2U1%uHT(d;z!$=+j3*oqV/F.Gb)RYm6c-=s.$cmf@\>ci/;q&B(n,_PE0n[0_jmqL^;l1ZbCnXl&mbRco[;0c%EBG;G$31&+!!!"t%>dJ>l:>h>:f/bZX0kQ8XTBpc8m#14E^F;kc#cR[JbkioUCt(ADC#8_zTSgCp]K:?*'G_H^>D'P3mkU7tV^P`_*u_%q:U`f9,;jmCg3Ob^F?klLhb!!!#oE'[stj5Z?Y8j%@fJ4?<1UniCB"l?h5X*J1=jlM1+QP]]&zW!=T6^:q=$Xi-u)O/Q#mI!khs>@:+BZG"R!!;p%4(A_p@1JNAMe;[ef]S`T2"b?;5Tk3?ng9>O0p:s0-&kbGR^UL=u^V>8,@H"hBmloA*>9]@WOf/<]!&Y@RjTKq%4h,RXMM5"%BB_!O^#?2T7o2)KI>n@5hV2X:R@uQR]ba6g(=u]oiOLPB--N`fE.46Z/8T!jP-i9\-:TL$cCR(0q9#8K0*^O'27.`70@P@BXP$_OqQlL"Ug^l?(3aX&XplkeaPq&N8_=W-kqg`-XgcE"m,&_!er:]g.VnE]W[fK,8(ju`(Gj_&S\mn>n`fLi0'qK&C,RtiQJR4YX*9u#hg!0UW2s0:\83Z`Au"t'Id[TT]A^;j#']=L5u^;\]4l/gHems5e'Tcb/6T8ecOp&DcdNdpLTQ.pbG9rjc"WT?ZKtZEPeRp/_DZ<*!:UMN`:Ep+qeoYp-Vp7>Ml^DK'c!7kZ\rEjQ61uFR;W[Ac3ZQp)`oCq\(mf(YJ:M)k1n]G$S,l\8r'mpBR<'8R,oN?Cs%\=O7Pf*Q'/F@f.GJDCR9up\C$4fNjFVSQ%U2&[ShHt]pVgM>!A_2Est5Ln9248DS)?tI9^0D=>"LQ`_mV,G)O;EW>e3i^Tr(2'NJLt9V/2f084Fdj]m9+Foq`u(*o1V*^#6n-([8H<_uVCr2m[:.P!$7?ddfHndQCkKN!Qu,,V67U6"Lcd1-!HmG%IECl)7$"G6>2>la@K+Cr2M]6L=sG28\!p[ZL$-;Q1l-teZOr*?K/da/`>jr3M&)sM'OZtcJP_>I"TDoArc9-lg[gP?[[]U=WC%KD6,YAJ6,k%hSUrNb\ao9X8XHRk[fI9ks`hqgQ/GMTnl=>/I:H-9:W39p"5;"[hT=7FZ*lGEa.\O7p4MO8<7/CDA[c-RhFjnHALl^Au7@Z)d(fj]dds1Y`=ZFJ!\7pjX=.Q'o@N]aiP1VF[l\'2eO@G[,C,_Z;;=W%bK,9l'pT'Vks+.OpDW0fdoKGDr0gi/Z`)BuGf(5qar#D_rVM>E-HUD^Gcdu3lRLR`_X8PqpA<)UP,F]^X;H1GL@S#N5!;Q3';NcSHupOftbM+TdjMrc;3/5@(PRMG_RqdVQn`Zud_-.:Ek/Kn.4iSgiG)i/DE^*CZ^*/uEle)C,+YWD9<*&D)'NTbM0>`)h9eHDaq74l*cp#!pfDpR?dg8ugaphg?X>auA%h.Z.a>AHR*:Z$'lO#OM^E5+baGnYrJpLDUL,"ka*O>)AQTd.Pf-B^D-I?.Fhc4pX`33pMX@m?%7iD8suo7S`Q!\R@;][1W@I^F]J*+#Cr[:Lh/t)n`%NGr;?K6aN42n5T9H)M$B8a\3MmAcfYtfe=[gJ5LJq5$51GV$>bQ$np!8?!!&"pV`re:Vh_h*!])*3Pu7p3]uOcB7-I8n(@`fYCZtCN;m?fP=hiFM-.Yq0JWNC4]2_$A=@"Jh>JOY,c9oUPB463P;tP:icJ],Wk%N*8)dpib>J8edd/L/:5nbtcUMg3'bWE:F=4l)$3iS5Yrb![_f+J?D%dDKL;\Qs%2V):&+c)2IEUBuUZ"+^%-q;/*\c#.sLXq4\7>:_>.<^'2.CT::(+(2YkRm(?@`_H&D"'g3tQmo2<`0TAZ3j6E=Emc`7L[h/aY'`#?Qrg`r,A!dDJUTDf5.P[%I\J04CdNtc.hCGnaFd/QYZa:X,[q9BR8+C'l[N(j:R[/eeV5+/5./0k:*[ml-Do\,fdXlO7rDH%M?k#uABf$"<2-;VHmKVkHifkrtVQ8ERCj4$Cd@%jQ;<(@/-_34qNU@/S1^odGIe;i$GUj@C(eC>sOMB>T!$RX<%M&1lQ'IWu@fsn5>[V5YW405pg'alZMTWar+@ID1"\l2(^m9dfH$Qq#!.`)I`7rPS03_?cL6Yf6l`\_LjlAM/X5j?B>HpWpZD>\0nW0_'V"&3&U"Ga*=B(:5?,#;R(7:9B0h)ihiut,=a:RhBFA.3^".KZI,!g'Ig.]:A3Oq=+6-UVGNM(EsmHmhKGC*PAdkmfq'+eX>r?.&-]>?&1J;b%6C1:N'?,SMCkfjb#[Tc4utS4)d5\E0lsAoXP%B4+0iQoOiOH-YKC([;]r*s8m.>#C1;R<7pn'Do"YP*\!:#N\700KUb(@/bsaC/,.q$nkK:baR<]W:aNHj>9QYMs]^hr(XRO=4K.5G*mgEY4GpM:L1GQ;/[dP@WrB"<$#WfX9QfRg@1:_P.f'peugD+]\VB-!dg(cF=i:L1&pP[[]1%;si][&tQ9GNs'QXJ,1UI.kdP//([J(i<(*DK2rBkP8u6\$b3fWepnT<-d/`i_W$A^D)\GJdPgj[9+@6n]aCiP=dC[8XoLfH"nZdZ,)_KFgf/GZK=PaXIIRdOY"b_C_hbT8t=WV*MhkL02YIHIA,48!hf0/"b#/#ebT<@aC>Te#RCHS209#?Z)8]+&FPTM9`/YRmN6>Eo*<0G&YlgRDbf"^*e!hAP?1*`H%qf1*<&JHM@Nu)-AGTf%je,A9E;7k3D!Mmg:NsNBTE/T54'=qd0R(Db5*?ZtcisNB!mblh=>#TTgoZqbeDoD!IAHkW>Ah?i?g'A//0@e6PnPC3PI_BQqD-C9^b(9V$(bUoS0"!)P<_$H:o[5GXQ0?C."F-hg)A8Cp')eDdPgmM>/J1YJ^M#e2!0'jIs4@VGadKN_4G&R:7gUgDNhL9n4'*gG$2El.;g:7Z*0Y'=R'.p('gaPKXs#E`bFMT-@Nd5(1r4Ju55_n/Va+?-jRZ"8@ip!K*SYM>@aQ03#S12\GMLI%U'7f+.'*7AnA;I'q.4if(Q@KcGO*N,IH_3IU(Znp<4+AaP4p=$JnnbVJ8^rZ(pFt263EE1>RB,//P>%Df+ANR-]`AS2>d9/K)oDDAC1Q\qE.LP&KgMJ$+q]Z"kTfpqr#QUh'?[9=o3IQVS>;f9m.uLQ8N#ThXZe0:i"i$Fp7UgC`\6=`7Bs-dkX65U9A09#X56KTPE\m,Ij_rEaFeW`XFd)A10;??s2(/k8B6=ZOonJk'%%8&+ePPU[#C=lparF,o+nEES"^1*42h*p9pMn)i'Qp66`#lb0^7E\k1`6RSd#5B]/n<7X4?oldK/.O=m0&h\#:7Mj/&Z,UFR]m:Sc'i\.skK:`+3'2M`.glYhM(01.,_gWCld+@-nOZ%g'C@Qad!niN=Ro&X2W4mgqYiuq0#,[I721#qC?FMgBAM\)$;nN5p"[T$0!@+tm[cH6\uN`4Qfl%"hj2+3&/>GMcEYF)'Z=jPb$U#G%^1F:74ke"i'jY0YNUI!b.C%-/D?Xe\QGkQVT:q1STNt:"9A+I`:D$6-a2g5cJph(bo0\$)-q,tD?J(\I!DQ?jVof`9eS.is60$e]tN7Xh='13LOSFVGXt6g/$Lb5m*KtQYmV&%f%/DbcQ6:IXG_gb=I,29n,NGbK/-W;lgBIjM5LH3^,u:]ka0Dlh(ndM4uZ8d%7QUG!AZE!Z/h$_c,CL=YK/LIlch1e\sT_-8^iZ:P!kQJ@9M1+os88rYLm<8\GcSq4Yo^'iVH7MKf.B-U%3Ao.tmp_`nk8@QC8CDTGa^0%!@.K+W+g"Sts#OB#:C:NqX"9hWMQ3He!Zil;eI]JqDl2B[?$d)#DqVWe%kY?/3KYNtE,r+"W"DZ'T,jVu.mcEIgM=..+&'U_a'RIF)dlsUHKenl!:'^0W+&>p=J/p47bcHt(%"V%-sXi'`E_1`<.9_q(AV'\Pij[+MWRl=M><*,Mrh7TF-eI4QoS`T?M22t4KN2./FU$!=J>m4H[0\G#>3O5iptCjP>lrZd^ar6^(cr:o'4N>>9$;tm\$,iG))!H.>:b?3E,.;'5'q.I0"j&-n$KgqXeJ(UY?S;>d.903ElRn7moc+jQ*7H>,,Xe>TaYP-RU937n4XC+7p0DFMo?63`XUAO/8^sTDeoso^C\PDr9F-3m,,K'?fCpic5#!e:Pjq@qErk%3#>cWOq+qIY,[\-eM?/#.i+3PBp[MFH"!6#cd:$W\47h$>MD]uO_7eZ0t7$%GjbDW[O=a0!-IL"G6ag[4`L80s'tiQr2Y=<6,,A?Od"rPcs>Nk;run>'',M_?=PmDb]6k/$43WC0]KP=p=DA0-3mhs$VkI4eJ59;0!,7dr^?2b`5F'O>%]UHGUi9;I"oLRF;"ig.L8rTdN9f#-+i>I;E>eCA3"AWeP(e]R'OmT-40?*S_=1$dR+Gs"Z0'rK,UWF_$q5S)?2lfT3pLNNBEQ0\16]0&\I)p8d!Ksf-$PmSAB`0WA+e+%@$RFR:W0#VniHuYUX#iQ\!.6doFhJpps'eY*n^fbnI8m'i6fBR3X1_:F!.7abbKK^uM@-VAke=*^8gW,,M>6b7.hH4NSMEFI?LfM-%=ee2[H>WNEe>/7]/L1G=cg"r&pq8WG/<3Z\U:)A^)=9uCo1$_WGa[bO?X3PtVmMhKMW'>dH6$]O-0*ti=erG%+r(ioB.IY8m-Qa>GDR`Veu9=@70;Rl=8UJrba+_].Sq#V"AZ2V;(_Mi;#),F@ck#I;;r[.5V'/Oo6,&;#;44h9!;SVcsr_h6+;t]KPF3[aKp&tFqJ].-ToB0l'!PK)>USG0$Z>;EJ%3aN*b"+W;&XRNdjN*/eS)&XA8fXlS=0sWprk\dPr;BgdK#6=$TV,C[5GgT]EM>Q,@GF=keX]8P/'\F&'A2"j3!!)r7PiR)>Lo!rN7!8tTtVj,)_NTc3a/:f^4_r5P@=qXK\q5q"XX6eC:i@JBY-L-+%fG/J60hP*/]Cz!2)W266UutLkpk#i8s/%%U('B`PoeBz!!#8oPa@_BU5TgUD6od?SqmLiT,*lp8m2#B7aP=i*m%"T_mOS!:=Kq1__8[.pefBH050UBr=;"ZFp;iL&7d#e9??u5oJjq8*n(q4*_hCRT"hY7$3Ho22d5f]m^b$]@#Qt5)(t1r`\]sKt##k8M7cl7G5l_N+:ne]!bkQd67e,?I5[_/\U<:g'381,8r>X*kXTVa0cQM_"O]Qf/1.d/i4p5Nja6Al'7rtP#Qt3[5X)?XKii4K]=74,S&*,)c\"PW9h2'dIFji6?46]XD+:uVD,cr\bgWnVB=7^^,:BlPCQ'RX_O+9HA)8K];V3TJ$"Y(uiZm+eA(]L\EDqj)b+RL#?e'dFidrtY=.k?T"cF^i1\/hSu/3R=.f__a2i/"29h7mV7#Qt3[r"mfH@VL)Led>oB?,pbSMG'2G.oGa1hNCL-gi@9]VjLK.TJNR$1eIe6S<8p\O[rf6#0+Y>d4Oql6F8VRJo=7!PLRa^tFZ*_(`A97@MqQ[^O@XfoXr9En(#Fm]C][?0)2$a1Y=pu-o?&/G4*B&Qb61LcnUjM)SVkf]%t)p5k-Ro.NS3a>W:#eg+5scto6B4p1XqqNdI=OjY"'N#2b>R^H?nXn^m`0-gASVfJNt=haM0p@/!er6m]AZpa^DdgEk0Ur($"4#f5=h^@YshZd\oSd1DaiO$/@M7J[KW"_m0;:s.D)ckNQj)$/,r'OuO54^`r[83--O+nAtD'JGjHC^Wl)uITd`-LhITuU!IVg0aR8EnML^X_a6XCmU9DCGup&X>].7nLJ%T[2eBDC1RhfLK[BaPOb(s*$J_&4Lo(c,tdj_<1K,APXM8^W]46P[&hJFK68NA%p^G%iRrVDk-e20bn*Ob/bbXigi1K4h7mh=#Qt3[r4CFh@_(U-f@&J58'\Zdhb9u=X6u<)/#=+$)9GLh`l5qC]Zn[C\9-D\`FRK+`*ApG?Zc8.Ch+]AJa4MDc!i@EN8f6b'a'5p[kjTLr>/a$I6M8*9gh0_;"C'!qHbODN9=7m-MMn2\s6)?(YDE@.rbg+]WWQIn1l_2A[Z+"b=c1/tGZ3]c"?YtRqh=73=]UnjkeCE/U6Gdm6@ad&liCQ?2:VWn9lG`Fo,A6"4m1tT&>u,@o5T(Nqi79'9P,;H=G!.'tlX+F%=LDNeJ7j-8Gp;DB<.@q:dPee^E_Bn;hGSYm#8cXt5lt36NDT%,Le1-YUQ)4u9l-n70Y9`L6bqL&RWJo&CHlp7?IE)fmZEVRqlWUgs0VT7M0Op@dRVIIqI@17?XY>BKbf^6=Nu-!'`QH$oo0#J#\#M2W$L,uR@"\C_X`<_3EOJD?[Mq4!DG53P=lL2T)#bOE#Go>D:'SD/*a<4dY?+:ne]!r3Y1'ub4bWLHP(=]m^j6WR@I3&lf_"Y30@UkhlM8BW[%4"^%3oAh?nP*&jM=ICUr-"_.&I^W$OlDDH?hANaXOFld92>lC2rX88dBLT0GTY($!m.#$ud.X13k4t/WCdrT@onFojH["i/pNluU^Nk7G*g8^-RP'mS6so$b:X=]Ip]_KY7`.sFSX8]K6qrSQA#g*NS8iu2lqU3k'3Cr/^m3Xl$,Y1;/K0KRo%'oo6kj!FJMaq`7NPS!43CY!K6E<^%eQOE>tlT0lVEOhdql?C.kan=;D&,*mmi/gC$V>T]+6N(].fCOga3t@PX>G9rdc^T;ojC+5BZ#Q&-g[`?q.iF1k.u=Q]H4lo/mSIkuC%M>Jd-HYF/Qd4b$0Z1T]*e<39Q$k*W8\+p/A>/Y+LVA%R*SFp]AVkpBQK69]?gAOYLJNt=haM0U7-'hc[m]JV7Z>d-a8Vr>>[\K4rk,5"Q8U?-VU%#G]1aJA7cQ$"%b@5WlK&bA,]8g',i=hNESXU>ed!>MI\Lt:^$Em5V2*6jRnkLg1Vqp8-XnIS,0CtT*g07?srtnWGP>-ILBi`"JCS005-/(HD\H>#7J'^EF9ViLKae9Bfa$ef?iGh#'2[.^Ao8o*n2Q9pTWD9YWP*-HA;<"/fs1WRS[?&FC>H5V^]OP24+gsCq,!)KZ=OL\4mltpQ6$NI1YTW,rh*Vj_[K!au85g[t^Ub]3&*VcW2i%=r=9teS&3@RPi^.Mq$k[SpBC4498UZ&bo$T9&/FhjF?"$/t+=7!P,mf&r+@VP6*C=Rc'G_?;'JNt?>2G.bA,rQ7Ie&pC`Zf,nCPS9sU8Yskp;H@cDX/(tc_C7+V;Gp\QKu5?fs8K^rE>&PIVIF[K6,K21o>ZdRpSjJ0VgZ>VI?g4=@M)$h6G^bT9e2b:hk2U(,M*nIad`"jrp^93^);9C6*g:Hug-@'k6uqVL3_o>1te$k2ng/U*,cGFPiidIf$-`=5js[5Kl94-])%$R3PBV22Q?7pAAsLfVr*A!n+$Q8*Pqp]M7RLmGG%@<_)QVA#A\d8to86&5/gm@?,-C%I2WGA+tO=YHeN_0q-m'M,ZJ]3D&bTb)Gu"+r[l'j]P8H5)"C4o$W\l25B+LNd9tTGI+iTiNK__\L&s:!eETZ&4l,aQC4#mn2NDMd:7ro=Cu,Uaa5Jce'kkhANYE%8i_rj`:B#3IX4jS^;49_(j%)_?qk8h(q>_`d1glp)4O31auUTEVrM:K4+m+fF?6iGZhc[&C`JtjW%P+qCoYW;.H\T+;U=&%4&i%li0EQmc+O\QUl25M"O4"-Y[?A[!+)Me(@MWjqZ,<]Tr:GO::H,nPDK/%P?S7&r!VX'31h$X8Qes.6ZFLsb^jka8oMNoPWGd@4ffWt/PuH-sBPDL(%5dCLR*mJaeO5TgUDjBn=@MkuQHO5\bR.uYL7D*(crs6D2s3I'0nM'WeUEZShUHi["k'So.D;$A#'&;fM_rHfIHaD,b\qpRZh%mEO4o16EM[iEBd]]7[,Z9'X6hH4j?l0O[I4iMIe(e2Cd&-rC?Bqr%?/@V2AhJg\K_,`@Q>7^8lb!s>?oU-A/2QNjXl?tg[Q#Vg*1I4LXC464nq9]D7ARRm=_ke2G":qP3B&RH,+]hYrReEeEAkO8jl)2aj\<)m+]'dc]4QC[dW!gZt#HMp0HF]n(_Zb"3&XJkb6V3K,]'Q@FJ.f1`>j=Kg@@acU_ETlg2dm:@_.QPc\TeX?V#ReH+hJq_"h>eH]A<*l$:oh`D)H!eEW9Q"cpoDDSo6hXp)\__[TRNP)u'*b:3\-DTP,W`;ALmLYqTa3S*\bmZHfiaq?c#Qt3[5X)uj:b4OFo2rZKC<'3;PgiBL\gnqcV?ZuPK?9e$M2pE)hgFrh9@W%VrEBAT5TgUD6tKOGQKq9$B!+;0@b]98!ABR8Wmb5[JM\V(6TbeR/Y>O+2BA6omc_6WD@d'V!eEU#^pHK\B+SDQWpK3#L[QHuXC-J%Z-KRQ:&-rC?JM\VIPWTklYhbS!#`*%RVBDKN(@oVfb2VoAI0]K5L-Qjm#R']1`H]_SG0`J74]^alKt`"i^\"f0h$1g']i%7pL4oc&3H=C[A4/V8;HQ`qJNt=h#R&SO:rq_ed#c^(O!V`bnB/r/?#MtZgFN*\4BnlXa=8\j/*m)=kl:\`!!!"YP*)>J@qd)%MqVHTraE&_/BeV6$blY^-S-g97Vf(%!Dpas^h74jP0%uC#/,-e-]t]EinoL*$$d9Vid$Xcl`_03M(rNr$/[/q7F9MM_(S?)3K9=l-KQ:4Y`D,rC[]7Kz^rMF&/3[a[7j8QFVo5k`TD\2`?V*gDO2m0:ItnH=NHP['aWbU?Vkf]NR?>=Y(UZl?'FH95.QA_#^:_*P//D=HLdWF&M]!0ErSiP2UF3c\/r,shpZ0Nerh&$.m!!!#okV:r#o04Oeq>'+KO*o-n3)Z^ifiMm%Z.GNcD)@WOQ'GLl.HQe[+L`mR.8EZ7CUmXr,f`Bg%20!N\4d7QbIOIGC_RqO.i)3ZSO/),1?^0U>>i?/]]B0'#ljr*!'gpkWiGX]o.r0Y]7/R7,*=^djF9cQO]D6@n0Y6"_^XR7b1"g8C2-Ds1-IcH.63trb*%os0"2Pj,bNBr#^GR"ZEdA=R(."!UBZ6tp[E9AM--48RN><0M*u*bQ4!Zm!!'e>#FS7LHLrVD`H$!>8kM]n@*,:'-#t7V8F#8''?bbqT'uW)*);Jnk)saI]faA]\SYc?-qjh.,<_SmV\+Ep*#fPE@AfnH1[)2XPXZkYKLQ*>as3,2E(\MR)Qb.A:"[X^-]\>s8&(&)0-I$\6F09V=D0FrXXifU>9]BS+jp<^.M]I/X%[&G5X1Wo14Z>=3NNA9KK3je.RS#52E6D^68obQ5d\Lp15!FDb===l@6m<,=R)^]b%=dL>oR:Oi,)&?U:._t]j5kIOo#k)fatS6T&TMf5CnXt^GuX^iV+^#b@r>Gg9t7QKNPSt3L[+0iNnX&m;d!*V:I'A@]kPKr;7a?VIe\9;_-7d^@LLW433P-mk5RGb"BoO7pO=bLnVh$PW`5<,J$H`YnP/(-2VTq_pMU;3D1)*@dW:Nj.DA&9_$ca71WPJECCM?Xo8Lq[:FRJf)ec2L9jG!02"mg,NH`?N6"**ahfW!j4$,Mo=0H7V1a0,7"o4jeh6#2(Ml!nBX\UQ%Q5)hCci%a.>dR"44$=pkgndK>ib/*Jf\+s89eM'b!rr<$!-PhsnR>U&)#As&@%95uVLd.aAr,Qu.8sj'RPea'*!936l2(8Q.p&liOuTkK=AgPmpO$nG.U$D$[YLbbDGF6%>,C"+;c?TX79#utQZ1-dKS1\_-&Ij,q'I*3^U1A8cf[a2#n%4PPjeC"a*pQ`V3OrSI!B!EAsI0j_nj

6_<+T^R&2[M5;WFHHKWd?]ABQETGBb4_/8GLPMS1g;jC0S\,7EZr'`2i?mdF"(FFK/GJ;-$^iaX8#!hK0c9]$gfQK[^oS`0ekD^pXPU1`09I(2Lk#AdOjmf%3p!BQmM=!BY20[2W37*Gt-_XDR@,XR4;;fihM3S27W8gU^jnGe^*Ggq$HqgA\'-Ec[4X8Q2=6_b@t'k+J%'2-KCC-@q:_RH7a/:IUER#Z'h-anN#8h84\&Vh2-+6ks#-NNqEd.BZR9.cmH0>deeFcRc9$/!cH3ahH&\2Zj`akj2b*,q8?["m>c^poOT1>6fP]]Vsi3d+*cM*g3a0R6F`U!`R%GqX83,m*E88`9gX!$5#3HF&2A!*Ufq@i0JTE"?;=Ih_[FamS1pF%dDlA>,0?Z^Fgg8+6-H:gifg+WG;Yca"hY)\Off*e[Tf]%X/TS6iX7*N<@'5q-M2s@5:g"/.kEa9*oV\3BR#3Q=DH9ZQD.gqP9IqNKsPE!<6%k91r'N3"[7)T]YfJ=]re**A8rp,X24>+5S1(OfmU6aN.%F9#b6QM8^2U,pem`SV\E28,i8?`Or$F$Q_IFn)Ja2Q/h7Q-Sd0GTHO9+c^gQ7Y,a";H)+[`[1F3]*[ul/MuBoMgmi1q@6X7nSF!?Dm*&qO`tCBX0b04m7gnMCP@J*3MJ,t32KA?^Fcf3o@`3gf0IJL?>J(s6.&/CfKp#M:`n&)kBIPn0WcFK6tAJI/gNh\\!_&BKkAD_U')6JQ'R=oS-A:V(%qUU]u3@uJ:2MOSY,nS/?CU;e^[X9]?KMpDbF-7Og`BoJs\j25,Q['CHIfJ?;o/?9le+V%HA/bOk84mO*qpI`AZ_PJPsY@Bb3X(\gt=2PpF#S-n8^jd4CO*Bp@D/3p&q&";rb0%l^gtWki*U.[#iq-i=V7ZWT7N^LWoCMhjH7Xmqhn.t7P*cs0?l%jdF$q2qMp8POYfY255jP_[iT$@>YUN8#RXLIdUtR:9SC/$\P/oHN.=!Z:hPtLZ./j7.$>B[b.QO#.8j;A5%For+#M&aPLKdACU/WTg;b6>9D.IWW"r#0"N_Fo&(I"m=a$R8Zo#qJ@-#[kLRo2?,3.\M/??olml@tm/lIqT.WJ$DM8H:#Di-p@"]&Fj/j:QfPda\UpXmmM/"T[&G[429m%RZNiB0$382Z?8!HsDIo[d12>[M*kkjh#[H>][:h50<1c$O@@!!!#g0-W;4p=qZL,SeJ.*#oq?5(';V/*=VDi>m2aEj?Zj0#YcEUXBK*ZSM_N!L(L,ZE_Knb\/SZXPYMfORF?nUf%SfN$8TH=lh_&8&44X8;QrQO7c&mku=?Q&FeKTr^1&3#K-'cIJiL9LBOj*gO^)aC1BHI8aGoQnYM$?gRk0V.`\KYqrj&I'O@eD/DjNLP'e8:SF=*c+Yu__Ms:%?Z,+cD'OdJo0Z$!>/j;m>=('@0;o3E5-p5-e.5,;]l*S[$Y-o/7`>969),-(5LZt'9Oe9/9\V2bQ4^WkdO?,PKie(A8!!)r;@5&Nh/CCVeF[:&J59elS[1;>KAQda(1GRJio@&@ZEO=W6rs-OD:A>2jmfj0PsibI/nQllFEG[BUV\Xq>muc"bsQ65PP+?L[*uu%O!!7La_Ii1W-!ah*]&T;tZB920Ma#Vt%W\@u'=4NZP+5eL?/$lQWFkB)%p&1ZddsBQ;jj5>GC1g,BIj_ki7]l`5N[P4e;.MEl&ZH+K'sPosfnYC%uP$?EOqIZe&8O'(CiRb8:6]\G,GYd:ZWE,iYc3%VE4"nLI(E5-0)*F2pR?M=b#M6.X&QS:b0g>es]2@*N7=PGc9SNk7q`CorFYe:r]qmgis#lTLKrLG3Y=#p<]^jhm;cX/eZn3H*:QS/G(4[#(.2e+8khTg$(e>\YtB?#lJf<8QYE/)6kaj/&5['kdL$I9s[-76_%q7OZ,"EtBc2YpY:R9:C9#55OC$OS;lhM]ro$WHH'R'd&EfTP1.jCZ?%eHR%9%iM/JrZn>]*[U^ls.SZu8+itDuhM?Ci?lU[i%UW1qKBnOSYcGd79`A^XslT+@4b'LM!Iei7[=iJ_ZF`Mn5=PG@`'5tRcgC77bWH]-HG>d#I?Wj4MJ?%eR?M.I->#f->l>F*qW`7M>2I5,o!!!"LIjaFeEW3U^?68o*ILQVj#s!4tgl373pjB/)UqFAQ^*cSAC1P^^/QRO#Qt2UP9-@k/gE0+Pa?6(A+AW:^H+l^%I^S"cQXsaHM8bg"fjPa`[6r<@,PYTP$;f2+7b8C<mtR_hUN/l_@K^,6.]D!.9G&"hjL"odqR?^toiIe\/>s'MT:"`;ou?B?m$(M2=eq8TAosWO(0*jPcY=m'#C/-H*rY]FKDci;Q_8f9<+mn(YV?S@R=:-iRd?RbN^/M):K$=?t$RM3!RCo-WbigZXldjIGQfjI'\-ZR(o,/^2J]HMR.-WO'Y4*,YVG4@i##,E[%&1/_TAU4\&)S?k>)m._/7T=aRK7OKQ0k2p25g.0kI==Ocaf&`N;ec5[M!!'A2Cc:%ncJH^d.O69-.]p8F=&i8^jQ&9^4'Pon,JC1b<`?uCNUkC(KqfrVfB)/UUnsq6,poFb,bs8EPW$+n')m7p3&t80gAKt+o<>GqZkus`XjXGo2B\:cz!);H;-'nR_&@>go$IBLA.klT>9X%I!!!!@2\NCjT^a'7bE"U4Ij2NP9e@N\S7c>G&KVhlG6J$J!!!#G&i.naOAq#d7-uTt+I;C0)RV9korGEs:Saha80jAlDNXu"!!!"HHm",.O1l-#E98\gC8^!+:nfHr>>"V#ru\3a4es(+[/@@'"#:''WWUI*BNrYfs>-(M8OO#me/C%+:ngSY4`9@OPHbtgRiea%;DNccH#O\2HMz!!$k'Hb[`/BJM/bGR)MRz!!".>,nKHp=98I&zEa!LE-&*0?Pr+@qs+_1nkG-";bnr)cPQ9A8?A`:61]$h6Ks8uQLk_a9B2;DVYiQ(?uPG$^&Mg;ni[eA8V/9jOct%Ykc-)h%dJcb1gnP'jbIcp't8!TOj/sRXJ#-Jl9BI/N2%UZGLC4Q_tH4$r41e:-T$))aH#:"?@@tY]6\VYlNQ!brf;Y2iD9kWYr0q(moaO8Le^_fD2"gnHOgtb)etr[[i7J!W(N':[^LAJJTu/]Q_((>HjHhez>*XS&/;4u9N2M^"W26KHTnXKZ2^G\jG!p9>d`6FUXgK7dVmp5J,M8(qiQMXIY(:[[<>8=/a]0r?&WHA0*)%Q!8un3NQ"dd`\,r3!Qi"5qc/Y0ZFFA#Ajdrd5M>1Zp;pmhm>50/=+0J4i?>roj%E^oc`s0@bkXp;BsM@d&Zo4QZHrqJ8-ackg4I8H]D8uELq*skpY<&E=Nj$@L4]^HB0pE$sa[fDOsC?ShKB(=^0?37\?aEQkNr^H-UJ+Ku1rr8lH62;fpLWXYO\q;YeW2\[Sc?&(@E?_hAL7&V4=@pLmrRh8rRJD[b3DBs]17\mip)i$'BEWt5IkuIrtjmqmuehnkNi0K!!'f)5b!WWkP:.A3n@R0d<.O^%'p/7"juF6>3M!L`uBai[s\hHH%#Od_QdiD]LOXXeA:#.GJFH\GJ*KXCG8gRjD=lC'E1?sD$pX.-^.e-`o9F*AYT+.ou3#E-5/R/9-Ocg*>[qdR(]k");SPd:'hJ#DF6bT/lrP!!'Br2AAg0o2U3#eo]_iT&rXB^2DOFI(d1ZVT)#RG0@kq4a$iRqOKg;JOWlq5?n&kNoq1'.!BNgZH.:Ja;t[U&j7g]CmPI+7)V"E,J%@">?Fn-pA'IImp:,O]pS"K:EjfWHg#;+__qK0SG^7Q/cWIrNgumsNkb]CVNaeo%S7@ifD82,(FOB\[d9DD##qPImULIA=`RYUDpJiM8QM"3nSJqGAe=(hVs&3_JI+8V%no!Mor(14%%F&>Qm38K$O+1XuF/n-jXc?MtIo!+n-`4mOYIY7\F.tgYY*_>+GjJcFIl`"kh(,M<+rTRYYPhkA[XJ4GTD.K>jgG?-I=n`#XgjOUr;+]aq(20oRBTr$3(8M]kH;f4s,\gh^V/R7q-36X2WNm&!!!#7IuC`J9Ch1O'X+[3r9<%-7qcXqjVK`8rALUL(@gm3o`\KnK4\3`RQ&\pQ/k?C)\,mOQ1MHZ'A$PTY^Fmb&bX37GUX*,IBY]J'JZ(L"$@'Y[o$]>dA;mB!k9;>=bXJ=8J]QNT4C@`%?rK2=G*n(<"`o9`Lh5>D)X2Dm+Q[:pA\`9p[>qH%=KF5,Z'G/T]#M8hn?510/d:Y..SWZh>N]`Ss=V)r@*Bog[!C3MnJW0tu]W$dnJW,7FHrM7Wl!/35K#s%ip&$3n3O8])=kH@`gA.SZTNS,48glYaYc],G7X/Tn,lD:>Vg%ENA5?%?+?n2]5T0IT\qW<1^?XX`Lh&3Z!DVqlV_fLr8-S8f^S^FmDO-dP%!.X.Zp-HP[`240QEY"]_gW$Fs_r0.En64Iu"6c''Tf4/0p:dRkKni@T\Re[%(n-p7OHq*04M!nP;tYQ:,%Jge,qh*>41.gBqB:lBk+'!+?7B+Ar\c?k[mVVi.Q+DN>_6&;m2loHE0$mW5>IQ)>'pVf'W[q"5dL+2uP46dk(+*H&![_C2msY$p-'ONK-Skl#4EJe>`Y<(JSpn:#)7$/?Wm^Ir20/1Dme].ls1:B3m[T3ZH`OrAfZuYg6%877#c4q^$@Ve3Z/C#a))H:RlA+5p?37YosJ?Q@)L.teTs`F'.g2b/$CVTrDu@UOi\mVAb"%heuE4q?mLI^2aQW?=ttkl?4KNaj:rH$I(?uW9puhKFiQ,]7r"MO]]\a2]7ji:D>PbroJ-Io7mlZ$oD\,E2.I+JLgrB241d!OW9P"IP0!&;I"d9Vg\'i!jB)[]t<12Fj2)j'pRD(5b/7gY$*IMr9X&JiA_'#:V@W:!DI>o!nX-KM/hJ^`Sk]ko-:)obQM2GuKL@=<8$a+ndiLV0=h.WdeJaU;h#f@91l`p#nM8?LaORB<.p,XKQ9R#&/_Y3H!LQIbfXVm_GN(m\0dJjBt?D5N!FIcd#f4me8.]InTYc\\2hh(e!rG.^=TEj8P"72"\Tf.l#0ch#/!"?/0Ya"F%\6?T:`N=mU"XB4TMA+\'!5$HbI6'8;=B7XI2VaU@hd,%E=qd$Dbm$Q_ZYfmq.gcVUT4QAPrg"_P2*5V5rp]AVFcYS+?cO'oWI$mN26)EXBT?Ht/_,)Fo$gc'D/oF3A1B>)$Zbi[+ff+9r=9A.r']+AGamY^[/W,.hng;IdY]nTSie&nZZf__,YJ+;0Yg#kZ>?-lGBZaZ)#;t:mI8NFL^acYjHZ^)[6$[BZ&@=?j9-WFnHt92q!;A/8*4V*dR%5ZX1-\fX^fMd)REI?c!+[j(>VAKY6/<=$hLh9UlJL=)*dGH[,p(h[t!__">BSNh+4F[>!:JL3V1*!46XH-Z?@k8.X3*Aj:b-P*?_7k5TpN:8O'`I>o-rX-FE4_f[clV)_bC4CQ.>]L5`Ha7REfjHUmQ>orV3nZFjTF^dGO,S*9#G,22g1qMqGsNiOT&Q3b,2+Pe-&*Wmtm'Nu8V4n,6g?h[49eYgbfPH35aPm"#pl\/,VT!1YUKNo^`+mu2-KU$fIeZ3r`qY2%'()=ff^=>!uo,1`tpV*\LOR1Ktgel4kLnX9V,;di$H:"?1*"@.-]8sKHijPQ2JFB*):D%^hA.\tfhbV['%Wn$/*qQJ6@+#BD(i&m_3POrA:DOl6g'Ad?$LZG$+,3^-Y%AiadgU3-8.F*h60MCq!r7PfD>,r1Spkl`*fRrVuQTppR!b65J)F>IGO?q=+?@CP3^@VCTsT>>-NIR=:HXa(:%GSklWL;!8ns=@_n6+mFASpgtrO]6=-&GCb5oPb3E_gY/-8`2jO>e4'_Lfr`")59A[/8dU.34^0eVs8%>P5bo;#@-CZ[o7B02#PS='(YUK;C-dXVQTg=JJqq4bMk\udp`(KepH[tV0KV.ogGE?UKQ0\_,<5Yl412JH-,Ot9^3,n!.]P?$[u0%7CpcX[lV:3:7C5g+IWd'dTF>kGgcZDbPJ8(l,a(Ls*Gpt>4NX$jdrV,C^$4<Hd_@%_kHYeTh%n]*Lf#JQ=S"I%YRiKq:CSMnZHf7*'n/8/eNhn!7q@\c>uZ_N7F/#8In*phs_[mo;+^`s)_op>)sBrXML&@$rV/TD-6bqZ;dCon-p`;LB@Ol5EH&$A[SffPbkB#i,@7@9iYM3%mXeK_YHpnS8\+hK;J"hApl=Gc6ChCtr!jqO!!(1H96uP#lMg5.KTH@SdC<"B0^?UmHc+2R>%*uA0PU\=m+*IP=gioqs;/)qGDRK2V%BReDEJjQ8,q6[P$kAC<3lj!W^##K4T[H2)Fd!i'_Bp^G[t.P$UGn;/5Oc2tJcYIqc><[ZJq-"A@kr=<*!F'-eB>l,;9Ke`_[F.-:mdQ6Z;8-mh-71V;(VVX"Cm",nA2tG]%O^XG[qLr')7t!k5uXQ1DVo[%e@E4IV-`7"d\tka(@+Z(kID$3$6#a.+q]`]4PX3_<8"/Ie8nl)&'4[M;lTY;CgQY:7!Aibc]Itg2X`_lHL<-3Q[b2H6e(jTks_DHlVcd_3-OZ,8`N93]Nsn-Wp@a's,?n'FOJ9O:*&&tH,VVRGLWLVaI=LhdI0@de6JIr^HFZ4F8hK2oLu@3^W3^>%ajSP&]A)>Rs2sO$akFL:?41F"k6IT`]:?>6/_]p'=l>%;.Va*/&gjdjEj?ABBIeCZ_cZ-_FR22qN0@@p]a=&*OXL:]?shV>]CJY!oA3aK9>GKEq6];E4(m*YComSS?`[#[,uqJb?$WRCL1gqdN61+)PHt-rH7)r,:qoB70oTmV!iG3oVuGI(G-_nRa4\Qh*t3Y$B8<@QMh=(4DbjO4eb?g5h2RLe^MkICp9g3HY%5&RL7NiZ`3CaF1Kn&TDHFRJ#2<%`7Q^KG>m_'%)&[$?.\O9!!'f!eoM7c0*(%u=98I&!5LBUYQOq+!!'>jYQOq+!!'>jYQOq+!!'A#k6+FUH8TQ_Uos&eiLX!.pE%)4='>9U!<<*"TJ$83?qF[ldT1:W'kZ8AmZhqq!!!"l^A]k'ZTnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>TnzbQ>Tnzbi6SMQMDsKV@RBVm1c-pY-?8*/44ShMlP`Kaqa&%33r.FVcfm/zo<:KabhkX?8jLr/@8M4@hV:^t),_q12*^6i?T%eQ=.?tc*O[]/Ju]N\,'Tfep>I9lg\a,8*on94ig*o:A2fNTVa7..V%H![Gj5Nf-lIM/opO!HKkd-,g%1T%OcZ$$C7U"`u.r\rRl]8ILm#D#-JkG!F`j<0E*]Q8,lm*WMGbmqHrOe3`Fh$'A(-*@;bJ\Wuo4SiHgqFPDTWl[UJ"Kmo%ldAFoMiu:[=Zh"dO-kAX*j2Y4EFc160$W$&rN4qVrDRXfh3B2V%Lh6>[a;[&Cb3@L?ELK&2[k#P\-_%Q.7*deg:/.7q:Xn7Kq'][LJ6foSTiuYQUJKY$[Gr1+E5lF\!7+]Y2PDKjfS*j-A&EcjK<@OISf-re1``#/@iiaq7gCWU>V9)W>`S/[AMl=+&(]j;VGntdZ^:>0peBZ@o!^)c[E@9!in*W93?4cjgp0;2MhS75%!)3YQOrV^E3j>$I"[p*Bm07:Q0N#cba+cgm)`:`\),kkVCqO%(f9fIM_80$82VskR.epXQ^!^:F:E!<+`)29(eNQMiY^P0BA.K*IQ3s8#BNq2D`>Te"VMG-_#rp`&P4#OJ_fEoHYMlRro-26NFJnis+::?1menoP;sNc:*,&'Rs"Lc[S5QBaiL""U]4TaHS[12+06=R\n'T)-_(3l:jQ^,ckNX(rkITrE[Obq=kl.cC!s?6mh1MZd=8Rr]:*t7$PTA.omPWgR94""B_5cZRD-jjM\PV3DeNfb'/8ar+lKhSW?Jn0&#(0@dH;c\fNF&j=4B"bSUrkhm%s'"PNo<[5,qmI`(qArcX)-WRlJh+f@F#t]m=`!X=4'B_ShXq0QEg8#EkVeLd#*Ymsit8H>Q"82"J$ncLr@;r=Ffe/lm]-/bXC.I2jinQ9msf]a.FWgI-ien9'+_?7:XdU\-e9bf=1)5Zcd6];q;QZe=,Qtek/Y#TWEAD50Lr?d:Xo)Cj8HbR/):@L5PS)/qG;aa`i;h)p(f9/9:#uVSACB6PmIWDq+sru&eK]i'QD#>rEuV\>Xu#o%XDc/W'*H=R\*`G]7,Q\q(K;s\EI:)FfhHi-@$JQfR-6sb^j+o#>UAWbaa-ZtDcHd.HF)N/s;.BaQZY:':lL(LI`?T.!@M2mT0)EJ-?!!(qGB";('9X5X'-d/g5UHPLRppbkB$"@eVQDM:\Xj*.':%CKK<ke*cb^lR'=a3:_h078Ddbu*/JTi>]`u^Wn]tCP]^h60KSYb.c1lZMPqThGNcEm\2m=OlT*>G5_h[ErC"j]&9n*_F\EpU6p&%I]+b]\XJul#q1Ob3I\0H"sED_=L>OXts2FeQb1q?CTMca-PJ%(&*[FZSlSm\b9h.u[o_p5bhW:"JA37#Y%+HB)]fUM2*a;YYO#AQ4jdm&r/h)gj"%*:.A8qW\,Q@p1CmYP%tt`LW<*11l/iW/X*/8;d\#r\rt4;-1.`-1\bB3Y*@qZfLqCpD8m*I.aY@5sIqE7Wtd-9Zf-Q]]hBT6qJ+p)p#*pmB(\LlXo]h#HkU*FFRl=h3rP6-_!3PLrK\!`f<2aL`r&a!:VpXd07sd]:aQNCE#)\_c3Lgfi),/Zc;H2EQ+&:V]n$9YcOYh5^(WrP=B.])mrUqW/$:9M68Z!=lsi3bOR1=HXt`7F"?&(Nk!7O$C6s"m^2idKM%B.C2SJQ,`%o!X*`Vq$^NfR`c'/QciH$)-X)R&H!"qQiiG4DQ=#Ku]55&\FjXMR8i]cq!!)p[=n\>/k[_eb@r'?&8p\u/d6VDO8EFFJ1YC8;p5Gm'9\%mn%@0UtDQHAooSYi3S`EGlUXimCG0ImhC:^0WH?\+-X-jQ:dQ3#WgqXtHOBDrs1jQsrNXV.2&1j)hmZa<*EpSFM9q?lXArOp9Y4NBGA/50IDm5J&:$uQX8Z-kiD>a/rV9J8J%S?#6c-+\q[rhZFJ%:>^ET$'NMa2JeO.'&_3qIk81UBh_;7I,AGl%f:*FZ`p^[C>%!WmXOS=BjU1t0`o`ODlH=p16id8fra%/RQ&`Bo"%0h3GA:,a?JmpN%FNHVW@Ck*_cg)H(J'[3`KqdWrlr]CNK0W^ODm"]k,+>:SU\t%WYGgt4Z1L+)^#l4D*lbiF3]X\5b)Y-fc%AOO#B"$1VjAmUC[G!nSQ+I%osGSA*(<0@RH7EP*':/Y:k!l;*+*G>I3un1(KTZEWEM)$+d5N@[GPSu_l$Iu(EE="d]d/C;%/;BLPKR4ql>4@?ClX[Tc[@\=bg%,6m!qgOSK3L95f21'Jsm+#6e"bV-EhI^9(*U?ZGPkhS+PMD\'&0eNZ7!eT[AM:3-H.a!Xu8W@(Q"*SLp"pVnZt"j'WZkV[J#idb0=s/phsU`$3[%ridS$k?RI=51KW^N7]4hJN$M?F,)Hi>^+C,FUH!bO!?g>c>oL#Ld%bU\tt!N"+6k\PO)EdpD<:RblmBm]O"CFBb.C>m.m[2Zf-f!SFNU0B5Xj`$J^qRjC[\,]$h&hkhD*i]oS@?FGM:gQQ&t*"'dl=qO8B=YWLnDNSSFp[@(Rrts"8)`r!!$uB9X#egJ)k?/Gh_V+<<4jfSQKp:<,Q`\bh5*N*4A?XAu)=7B9a?`WH>J%TWV[:ZorQ]DaK$OOCdg8)B1MR5\j]lpKt.5H-5QeS7GY^UAO9Li`5=YH8lH!!'eGMZc]DlKmqlgX9k;ROFoS4gt)WVG5gA_:d',Hd+?PdoL'#aXL>c:Ygen=[>M:QBDpQT:"tW/=*[gEjuEPE!!)LIAXOU_]QGEMkVckqSI/'t_c(o$..9,sag0%sOY&FH:,RX2)rhph?q?YSP7,+]Fi7@Ih2Lf'^r=o_j)=`i@Gb?PNeMHFpcod>b.Q0?e^B[,@rUe@\K`];oX?4m1H$6FAQ<-<5.aM84[X:lO%eV-%d)@j51a[l$kP9#Ze9KiIiAJgG\bG)qtZVD-7Eg_7(YQO]>E5BaO'(in-E@$rLL,Po@7P,k5#gE[EaN]:K-=DGu/%%$.Y?X(7*Ptes7X6MWc\cDd2!3.V0Gt0;:a\7L-l.1g>k>QZO.oOi?Vp(,8$LB.1TJK:@qH!iJrdY,4=\=n7$//=N^&]kBi@X7QQ-MC#ejiJ'h`*[?O]N?C(Nc5Do4)q>W@YWN9.H?;8VPO39UK@&nk@uO0'\[(D<[TbJ!A`tN=2I[q>BF]\QdW%,+u22\7OJjctSDF4RNHmqH?5YO\^i%A%G;!!!"WITO%B*[t5lP.;rLE#UuL+0+S=bDd5Cm),c4H#rqgcri`*o"Cu4q<7=[UU7Rp4'9X'LT/^^G,V#_KX/X#8uVr(cP8"=mNee-V^$f0sDn;WW/*$\LG?m=a>1>5Cl)X+:=!"4BlLA,##Cj#Y3Q&44-/b]r,J[O$#<7/@FT)L+f[tm]=W^rMh<[;Vm4)sD(8`W\ANeH*o]](`2a,[:DQ%jme6pM15MDHrhOIY+7g6"RMm`Fm`CX9jHqW.7tJH1eBn/4(B#AB29h8&UZt`AS[6[CTX-PSI^%=d*33'^E/3E32f-^:ILG]ZI03Du4X%I>skH&#phPOSo?7s]D,os0%/8%"Q*l$c0%Ju.H"Yj*l'mVbb.bs,,n:Bk/T,+>K`APE9jZ%`B9+H@L;8P2oGE`&Z,12Zsa6`&!Zb77,1Hd0a:;UfVc30iRM7LC.;'3+:"XrllSD:_mkX3&]uoZk%fcS0:n)$6Kbkh9&EN6H0(Kb_8gIkah[*Y[I\?9i3k62XqouaKMCOm(_hE`Pe`=mNPZ?2Op3`H9aS^_7V%kpuII.1>7o<*)ApICuM:f'W^EjnQ5hk!GWr@?0c>o)?H&D0iE7k>b0J_t&nrJ`To%4F4KiT7ih#n2k#l,r2$Ku@Sh?="cBh:p[C;!dT.'tjC`LW3q[9@GdMSj$kQW#:ZJF`;#=eE;0s<2q;D'IHSMZ[R>rOXD1CWfpbEKhR)Bea2k]9dB6>8_g)a;nl5uEW1DOVI=jmAA,'*?WS_DUo)k7X<]fXb;F%n.7,O!!!"L9:\53K^DG"4*5/n^4"bE%aD-'@gN,8!!(en.i\Nh!!(4E_%H_J!!(6;Tu"#PJgCBs!!'6s`tA@P!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(4E_%H_J!!(6['#@J7Z!mK5]reC?FtOtWDir,se]GYXHYi>Z6:Ko[;)1@In`V,[@Z%Y9eQ"#X4B(*-:!$2!o@=I;M:gQQ&t-s)*np#<#.FD"U(20]f-q41!!(AZ/CJ%-<)d+_FYgf_%=S;!r/lC"li4E7rua)q]TeIXjTEG#ikg!!%Ph<*-(r:s1Hgg$."iD8O]8QO'N(+s,k@er)R*K2U%$+Hb_W\i*rR'c!(Q2*WUlF&qsP+e8H$+&D!=H"hS(pEgr'W)G/R2iHdqS_4"98FP`b!P*fsI*4YHPEjX+Pr\GBnQ/f9]+[Y@*rFMc"-&S/(ID?H_Ti5;MOL-_bN!Z^pbFI5bBg[e(AY+._uB!Z-CqSc#LaRlplp5Q$A[YKGY.,,/ScV=Ig-30j&tb_1e7DU%s(5*[e7,1V*um+p'';'!p&<3\K`l*cARbtM4*J=,\D-8@$8lDioFe#jiqk]*WQ0?TV3nT/2`W8Wi@*VS;&A#o,",-N6P[:r1T[8?H:1fg)be[6IOaZK+EP4jf8Rf[T."S`=26GKhdjdPnk#q$Lq4%@0]^A4^BR9UN#Y5iN&`WOA'MU,-r&q&m]-VHE8eH=HXK_9KC='l1*p!6DCZp);8@eGPG:JJ,`$9^!*TtNaTubAm)j4UlL*p+YQAok%>W,Ga0Ysg=lfO]/5=;X:F((o$BVl9*2/P%oAhn6$pd:n%rlYdCm!I"#Y#95b$E)K\MA/)S-87TdqTr>U9lYA-b3/W<^1J=mkBR_Y<.QA>0b)]kH80[aKZ1PZ?9WUojlt=Z-opHA`?MN_rdVS'^e:c$QSTY_i>S,u`mOn&G#LY:!SaaV_#O9$!f'^i]ZtsE&VEmK[b=?[4[i%khUJ1om4lmt;,&4Tto^W''n(up8JRWO.YMdqq4u>5L]UHQM?C2]iN*\A5/.S'?p$\=aK1t&!9qCAH!!!!;ObLMpLRoq^PHu^jnVVZ*d#fuuQfs3*T(;j3AMM<_?DrBO41A?fL`I^SV3F;i(sUu*6]2XAkq%=T;'_Y"kCgJ2g,#64`(BIjq1'b13D!!*$U#aPGj!!$CB%1SU)"A8^p!!$C_*\7s<'=Vl8)Aa2+',.]gfs2nsQ:+/1NUq6'n>m3Q!<<*"JB`>Cm+eF1kK]W(#L?]soBE2TS3(iVd&pZdf!YW$H7T's!!#9N.C[02K]+Fk(;JOo^o_PU!!!!Q"Mk]N!!!#C!l5KL!!!#C!l5KL!!!#C!l5KL!!!#C!l5KL!!!#C!l5KL!!!#C!l5KL!!!#C!oF_&zAq==rzAq==rzAq==rzAq==rzAq==rzAq==rzAmn<9jL=fO\)u/K3scHL!<<*"^^sFr-*N#!&j!=Z4aVa%"A8^p!!(As>N#P^NMX.pGSem#eQ6,6^OO#':C[@]K^iG!kWJ#!X]siFiaQA=DM@\N\KY,W!'I#ngU:)`([<6BYtki01dmltQ97@g]%rGPO0O*/o]^SWI@$IoI(5IE#7dQ,VET:rj>jkI1_PfGRl-?Yd+E45RiKPiD<0!54"GghF^uE\]Dt3L=aKX68kR76CY)/e\9-sJul`\'PnDM,M_[[YGTMpnLOh4IYFStWk.A%qZ78]cqdH5k[^ZtVDF5@hp-P:_&80X6*NW.IH]LGe0(Ud$%hg8Ot+7Voo8^F;s3nqcH%<)"0mGTW4MnM89,Z4GV<&F0.Zt_Ilere200]l`F6BO4U89&n6jjFt=F>IHA;`_B%+"NZsDJ#H!U^C4sOj]f(gGH/NBK:a;+:VE$Y\V[erR>Jk-5lHZbn*,9Z4mW$"(SMR5*V?sh8P5B*7lH]18L37+4;bR=)&i$mG#,M$!aDR;toeeJ/?OQ#aPVt"bh]qIm-beE3k>8`4tTe#N6/2JUQp]6!frMY>,,1IXb6AQf$K[e$aIrZ/F2(NNAFOh)Ti[4$d1ipoTPqs6Tp=#PY!G^32u@7cQ=gqX>q\UnBmff8AkWi+gJ*(8"8R;Q-Xu4?:uQkS@Uf(1AFF1@P"S>g6n>eOY%eO[^g:XOF;SC?PA#o9Xanq1FV1b=66B1eA=%m'3'Aiu5oefsPTs!ub='@(D=S=A!cIC#860dsl*BT0dG^GK8-%Z?S$(YcPRLG:tI:hM`N:T30>1nq;[L1/>dnr+oPsqR2d)l"am060TW^Qfu/T.dS.(]%FgI=20^k2TLJckaK4)gX=5W=2++Bn#;;S]_Z27fd!&cCteQ,<>,,hl$NSu)b(hc;iX'B]P(X@?qKMLTDd>+5D_epiA5XeVYUe#1h5)"JHNk(M.DjH?Sc#jmQU3YF=4qBfsN=&esi9>"ccLjpK9CH,AX;_k94MKUk?i7N@_+g[?7O?a]"u$Lotfuj(e*RMS/7t,kW,0F."@&k%kkt.cJslA7*3Z_6Tcd,S_k#*B2dNVrnqMV:&MnF'l)'eJ$K-RX.636==\J;R-`3#*GFgU%A].:R5lRb;edUm1a&]!&"=4,7G_EBee6U.5`H:[6Pr7L.,?noQg>a0DoC;akt7).,jhgKCp'qfUa?;qe@-?jZ<=ANX)/rh%-2lK*b0Q7Z=LABC"5aTEOd]]Tt[adg?MC>lSs=6>82>)sHTR2aj?X84bpqXD,o:[.aaKj7!aaAe!:d3n@J>lB5<[n.jL*HB"Q_6TboXJtJF"Nsu.N&jbcX-&@2Q0s6a+8fg5'A[Ja]H,IO,KWooF0nldiEtCsdY[XUNEdm=*>!;(+fCgB]'?D;]C/cLaps73KE[!>_llXGP1\;P&f<#4qhQP.UCtn=)Z(h1VI3Q!7d:u4X@99[C]A\O-][chnSi^H*ZKOOfGJAp*m'4Z,i/LQLO'U],?^(meTh&t&-Rg,J>[V]4tVa;_!*\LuAgq-Z&H2*ujCBVl85)fH9WqcOT>H[;=O%LH+:4DX!E>W2.IU-Akl3Tdn5K[5ugT\Xg(5Et=M+8IMAHi_J=SL#6ld2"Xc+\UX@^U0<#(g0*["SPsr_Ztn9RC6#XHe=B[NhgT8gF^tnfH3!HoZLe4_cgk/.bkftWkSnT4q=rK&.).mhM9+VBLPj3:W6]>,D$?BSD7U95BQo<,cgaJ=A5-'i&!jUBfdA\]?B(afGQ))Ra-!tA/9T]E[ujbWHR-dp:[f-CD;DSBd!8-@cdd?]7Wu&2%UO;V:NtKkO!PI#Q-rlJLFjDqaX[r4^EuNH`u:APA!B.82UBGbiF`I_p%lYTBcu4Xh;S?Ns^3-:YHI!04B)s:AgpTiDcB%nVR+2.(8nQBsb&(C"'hA=hMV0LJ8e;K]Gm3Wgfa4*LA8_88MBk4iAi`0XU#MJu@SQgtqgt$>aE@NA_lYfJYfP(&ZbZ2?Yg4^Ti^OP_!aEHr?12Wg*\KikJl.LD'F\o"]A*BQd^l.PJ%[L\*_ZWB6^&^McUF:ZqHM/>cr-I$3`M(HAG/N@[_n2C.hup#35rYUhjWn;Ptpl@;oAT'mkB$o:##jB7(G]hUMu#4h[K8##=n993)T;Ed/*9+_']$S;&,h8b!J_r$[R`@3u1aNA8E?M.up\q4M`?AU)c^hn&Eeu`-uE4VP"9;T^^GM/JZ0q7a0pE*Z:Y<*aDe^%RuDg*/pPpc>%g3/j&9XAT4VSq<&\('1#VU'@mn^r5IWCd'Z]8,6XakG(/RGD_m\)5VJafuC,.-b\sE;+TJXYH,"^AI>5T$jfpg7_7!2gNi`oF@B]Y2#A8IJ8:ie<)J1e,\D1B'E^6F6?>:eB:=ABTj:7JYe45SSE_X;=Fj<,*fWo(HPZ.Rt!1T8Tan`#4^F"9]Zjf$AVl3^Dnc.B]gfI`[5OloXOcAskrN"ak?XE@LX0D1#5NGIerF*\BI]rJ/dCm/=p[1ut'Q*\HR_QmEoqYQ5D*rgT@$?lM$GaQ+*mB&F&dj%iXf>pI+0%DonduWG%[OU=S/V?D-T;@\2Q)P3TP-U$H4)\jmO]`&tM%1X*A?]^3b%qN#UafKtlZDI\p;R0-T\FigT'VFTk\`N*Z-gosH/Hs3DUn!b,I\&==QOQuDku)V]qOG[>'3Z?,@ffE!Pf)dd_V+CLM'L_d]QlfG1T(Z4f=mGrda4GKJdeA*oYUbd$gR`+2@H?Eq7^*-_elTh5VW!3S^Tm4TD[uI=Q'sAc=`/LMjGW"h-s9Uo#WjJn6]N!i?0W:H):?FGAl*;r:H-bB\o39e>9g=.n8uh`9>m=fB_i*8-TTlR?(PnX:]]+$"uK46H)D_8V#J3`+`Z]_nkFsU]]pmMq[q^&*r>bm7oFK@cY<5'R7fpam:.Pfr!k?^%u]b^"LE3lJk2s\*.pKVRhN_%5@.\r]3@NuWV^3W8pC3dedeh0sqFf_ap3^2mOSO5U=")5[lj%A?i0&I6PVqY)ILJ(u!DOj^TGMl0>h-#1H[FWDG?*qf?c)hp/IDGJ`Xo%h*R`2S>/Q-6>5&;N?N`(gXrn%l01E@6;K,4p-\#7cp-@Iaf.EdeapE^gUM65JO.o:@`Ec*[^;b-i7bOQqLA/!\_HC^c@%1L&MB$64Lh#!gQl\^rBF#OT=LMtG,2@E:!6;7rPh7Gpp]TH3UQP5P_F`O2/Cp3g,;&Sjm.t\2HHB'J!KQcn4lrZY2`H0]mK3o9(_V%S_CMhfs50:l@is(F^&iIAW5Jb8fRf+?OlC?A=aY9ea9uX^1BOZZBK7sjHuAsYGZb/>Y+=`D;2LiqMgOrFhGYLlEOPHBHsL&'\[$GO(LPJAne&=ob'0h*_o(^Ph54lespLJq)7[J2r?KlXcY)Ai\HJ=[un(YUflGccJNM?9?mJ5rB/'>a5:Z_Z_%M?qQ7kUa@lO_W$BdD-O0Viie7c+!!*$9<.):3!,%[,H)Vr?rMr2f"SdmAYQOr>/73ep7=G@:oH,PbY.iPMQi9u]8#EOe%KJ[0rrbd(g'Q7Q/O206:6%>#l+!!!#_X".:iMg34,isD:tJgCBs!!'5@&!l6c&m)j"ZYAeSXITnR!<<*"JB`>CCuZQ/`R`\0Di)&JGc@g?X1Qtf_o9nqGZIlC2@,TK!!!#7i9baS@G_]pi?jQf5!!$iTKB:m*M?!*gi2[n)*8d9oAFf'R"?\38-Ck]!!<<*"JB`>C>aUV_fVb#2!RZACoHfVCDU#+fC"!7%&c_n3!8*58bCEA$[f/5<]oBE7hmVQ\mm\m3&f'Q^L>Z5)=s-oKzS+0l8B^bQL^Gj*M`Pod6/=Pqo2.fV5K\'B`UF[!.!<<*"JBa>?LA3YYRQ'>4=g`K#Ce;Q,h,Q8K)]C8=k;Q3.D8Yi3iD8PBjO+ir1j'ge8m9!5HV3i>0-')jkBZJJOdlA=Ok7?/^-oIlCgI.A0RMm]!!(A*9OGi'E:B:$Gk'G#WX_ZH_,@`Ac$%D#,)4H1+;!29W#muZ#U;,I$6tOet.,`?qJKn`ZP2pOPQPBQh4GMNd:V.BDCpt]AoTJD)[>47ZJ-h."/X[L'a[SE`gdnYC)B8Cf+&AotEd;qB\0KCCBSqao,ekB@[,>u8U3O#"J2:4>Ls5bYQT6$31(q9T03Lld!DCQEU<4/oL?3(PW/*FDds]+5KJl,d6Pt?DLu#,I9RS,+ASAMo`8jNm#g\5K<)pQ!>\ZT$.d;-*R:c`c";,Mcud=:T(RYU$EtL^WU8I.RWZ!c7hZ_L$6mAD_aj]Q`nUY(Y/hqc]WGD%Mc:%,K^r(sBHe`1/O6er8Y0)]RX7fWO>`b!i,FOU\aC/QN`[dftO.qCoSAisD#4s(gtTK_.B=Z`@rp6rgaZ;W8CM>@\Tp\/cN)mR#*SMR8Q^\VP3Vq(5GgGNV7>aS1.PdaQ=Isn>m[N@[scZSmcs1XW0lp+Ob/W%5)hcHbj4BSn.SUI^EVQk^B(^gE,UiH"D$<[B54_SHcjCrKE)q?%,c%*0ZjtS[3U3$c-c[g/-*Z?!B7)g;W[^h:F1,"f/+J7eoq8o,fes^kd8+$`Os)+'pA#kOVjdS[IiY.G[fuRNj+YL"B&cf?nG%*4)3[:Pt<[;6M"iGCI8?!a=V%Zm1!>Ao(I:*01^#!s*",ol(Pn[)?7BS6/V"0]_:U0YlP^GFFT\KIm565FCKhJq-^,X]"+6sK\Ek/h>4fWiBO6CDj6D:naQ#@?6rL_<]bMU[]SR5h,rNieC]-M(ah(#FN12$-l>'R1KPoa^[B<=[^mZD/)'oJ`F,/SN=]\PeXq^F_qo5dtKp27$7L=p8SV[pOP)CmK%)Io`RQC_I_r^>LK=/L:4@=f<3n+4M:F:5+6Pp[sUcF`kLc8g>omdPSKX(N_@;A]q1;f<@5Gjhi^5+igsPTKc%jR:)A`6uQ;CVo5r=6dN1-R\YD3c@['WsP)91S^IA0E'ko?bGhF!!&ZH2--rWK%ORF,FsBHWc,c&,Q0YuV%Xb'\1]1u\Tt/ReCm^_T##3>YEPtU2?*((Z&,%3\,>era^g[@\b@T+=imr.l&'=mo^R@PDU3H!<2-gHXf=dJr3Q*R\L?F2%7OlKKPaj&+6i@](RG--X9G3.Cr7mXV?bjpXmg"cgL97Np=\+@T@(P,4)SN)nFYsO$?KG4!oa^>(JJBo=!5UT3=dQ9aA$L$75jAkKQI9*B]*dK'SL$2$^FCqbn#=&2Z'i@pmb5/Vk))>u2-UH?ER[k?9A%Cp!lKhMWNcZEa_p6V_MY?lZWa/Ju1+%pSZ`A1T>(1KfW:TVQ;mA^Rmb6E"E1A-CugM%[QFWl3tHr!bS[,cEP"Q<%?X=5>e5%p&/ZJZ/[,&.W)C@Vn9'?,Ml-u2Yk/Za[pP\hn3X9Zm7ekH(eQe.]P:,f%"Rt=S>piXe+WQ]\T&"!fiM0*qBsUT"FE)-N=eKo+hl2'BPq8n>.B/R_W?Zdu]^tDKHT;S&L%'i)n^ua[tbKD`a]\Z+QG!Z1I8\IfBPe&c_p)_&>O?mbeG6qLiH5f^47[[aK9)8\Iba8ON<`T.Es>:KdqjBB2HV`0r]WoW*A"[r(?rIFeI2%.RM7==BXVf_Pj\#PfM]beoXI:S`O>on0qt]nr/[f9>lHeL=AASL9QX[lftq6/WLOcKl'p&)He%-oAZ><;[h\+$YEA)S99(dHHT_P6Gr[2T9=g4ek%)V47l_,ubHadh-VDtHWBIrX6)I4`/2[TA?gk'X=Os!UqCLa+?_:NW.o?#FtL-$(j+#-/)2dZ*K+&K`ndr\iB(prY+L)a]2_CX'27O>83T*n/kIhdBT.U1H(ta\3bBs-Z&_c1l!s8:'bm[Iugs5<0ZM%t'jX\-K;pGEr'Z:RQ]G:s.8\KF5K.<+<'k!!!#Kl,='sAD6hKLK"X!Q5u.@pR8"(X-K57aK)Y^#^Pb!6@)CdmKtkpP(Q-RbZL`g87#Z10kAAYHcg*s(e\FOiHDC^j%#`fd7j1]U3U1gd-o`*6:i>X+j0/*j"r^Us4jkptq!kdpM@<=PnLq.*.NpoI?sZTW!hoHj7!cHuJ@DmjF3hT4(R$NL/,7Th?G8i*p"Sik5Ncf;DS*#AAG6-U,.r050Lp3^2=$1[86Q$GrZLJ\S.:.WIM3jeH&1%hkWaS^^4)=r9'p\+:i'RP1O"g@o&D_4@(DZmg@%ugE;GfSTrVlhcY*i/b=7(>;Qon0l>e>id&Msp#(Z?+-78Y<]*A)>.&QO;7mNab)/9-_L:5\RL:*?K\f"Wab>Vb_or_\)%rL5=r<*k%/gqtj$Q71c0_$ShLT)Kh"^f-!V=c_QR+:K(cg#G9JoH/j"9g/=ag,I42KUTA>G5;j/Xn0R!?8<^5maQ;:9(XdT-g.H"]/mINl4@UqIp8*-W+)SnK@c-5kMfdEa\#"Tl$k)Z4.-"JTMPT9]gtSZ8R^m?Pi(_-LW_,@lEh205a\bl'>Fc1,3fjXjRX=*l?SQl-p!2qt]/g'%#:d&LO&i=gSF@kXBo_1BR)DP@:Wug[I[!MT&U8Ld%nuDQb=.F[+>06g4r$QsQf^!*ElMYbRIgp8ih]l6d(KPCpWDjY29cph%P+cG/)g5V)rR^NPh;J=)o?d[@!;JW12-:4P3qaR-\R`P?hCT&7`XS56q:cD*FC$!c7T/"Obr7>Fm/E%$ZN:bO]RBR14&;Gdo?"$PhK:4@4L]k1NFtoa_Md-0VoH,]nrcY\O^J$&g""$5ksPUR!5S2=nefQ;AW+EQKl([OWb36V`tA@P!!$=jFU$#hmtj)LlIO-/kbHIiIIsDC%3ND!z31)hJP2F:NK7ut8^"Ng<#aPGj!!#hg4XTV'SA[4L9HX8>/Y+F!"A8^p!!$E-8$KA[\*OnH&bWl:%Dci@FY!On!!(r2;kIH3A_#9fE*D?"^7B(b#aPGj!!&\0ZJQB,zrtl$-z?ks$6z?ks$6z?ks$6z?ks$6z?ks$6z?ks$6z?ks$6z?ks$6z?l!kgb9lU=7SdA2]cnfcZ\:2*&+%l;:N,>PF%*;9z2WMWZomhj@nc'C@pf\3K%aOM%GNULopSriG4dH'J!!#iRnR+@0-=Q/C%YXZjhqfkG@\U>aJ;7M=zHAi*PIjZR\h7>Hr/hSItB%aJ$9E)]>47?qEb0r=FQ%T]X'8o,3*?!(=K)l(om+stn"!!%OMlsTYMq#0ZQ?8iKJ!<<*2:[DJWg#;r#o_WJq;jfM`@^F[p4.L^f#)Q^o!!%O?n\8t?BjuMZn=BE7jVuhBFAGW.N]WO,!!#!201ZqSO!!!9jYQOq+J.MiV!!!!)_)%AW!!!R^?jQf5!$V+c)uos=64b[K!!",E_%H_J!(%5J!<<*B"Mk]N!!#=s/-,_N+9]Ln!!!!c&1dh^!$F\r@-R[^qpX$CPEV3jj)=WUH83iQBT`[f!!!"T,&XX_k/kk7CVHpXWn"YfkLlE)8XBaL!!!!Y,Asa`l@D[uHXS$U)<=!!!"&(Cc],Pl/NM[qBoj/mXf/YQOq+5bncP@sNI/\(Fnp8WnHo#aPGj!!j5s=FU.SWOT16\p\tdi+QW)-qPaf!WW3CM@2XY.;.LDH0naM\*,,i,ldoFcFCe7n*'=h[ldk*.nscae.F54!!&[7M-u_oV`-6>g^?iE3f1$Z!WW3c\B>#uKES&uG^X4u[kLAt=98I&+:S:H,6.]DKHO@u!!#7iJgCBs!/)Is!WW3c#_F?&!!%Zp=98I&5R;rf!!!"P+BS[F!'ggA,ldoFKHO@u!!#9?GeqgiHY[YCs4u;I`s8fW-TfLLAbDs!ZCPA0!!!#$fYQ"kmf)1+D\n14m.n0qeU@%m?I-)kla^L3!!%O*@L()ej.?iPXZHJ43NISQ[FC>@QO&lW!!%fd4'6t*rr)*Gl,h&hnaZ.sd?2K0EGmpsOpI?R!!%fh03J57C+r(^7'Hdo!.\,:?o``7rk!k6,Jaum!!)Q-%[NM'mN56>hf^iA=`Z,PHYpC4fiM^G#aPGj!/M?hl\:iTf(T[3WR"\\E@ju\e7@jS@gN,8J2?tPF8u:@#XPZt!!%N\"A8^p!!klp"98FP&-PW+!!!9jYQOq+J.MiV!!!!)6*LIl!.YU`9)nql#XPZt!!%N\"A8^p!!klp"98FP&6B=,'#>1\!!$3XYlk%,J.MiV!!!!)6*LIl!.YVC@gN,8!$MW6!!!!1JrdbL!!",E_%H_J!(%5J!<<*B"Mk]N!!#=s/-,_N+9]Ln!!!!c&1dh^!$DE\&c_n36GsA"mQ\HN4Ztqg3B9;&B)eVB,L(ohR:$=$!.ZKW#0UqVgaohpgIeMMSQgH4h2.SBR:$=$!.Zlb#0X1kf^ulo8bS!BSrM]=Hk'E/-,_N&B0?qZ'7%_YIsS1[9N89_%H_J!,#QrO*>^A]j%)1LQs2D=m?9Y!!!#G\jWbrOOG-b?1*ED9V',R%06G/+P^O[AO;!r5.nV9cs)k_&M*q_!"anbdLcHZ!(%5J!<<*B"Mk]N!!#=s/-,_N+9]Ln!!!!c&1dh^!$DE\&c_n364b[K!!",E_%H_J!(%5J!<<*B7(coAaDH71Z$5j.GJALrl/na&V5^cs;^o8I?jQf5!3OnidbO9iiK%mnLKa'?\HUN3o<2KH[q+g8@gN,8J2:X>bIQZ*%nE`_s!p+1IEf1LOfarUQ2gmbL_)XMIeNd>l07HSaiX)Cn^5aHa5_/X4,]7-Q2gmbL_MLEro@fJ79rN<'A<7(_!!!"TFFgV7RTSH/I&B/+JlETlFI?MC!!%O*iWdT0*n^,!(J4=W=.YE1@Y=MD:Tss%!.`WhK;CaX^N%E`fq#3;f+BP7!!$uXKqGV452'6-Xg'-C^*NnT!!!"PM&S"\IG.Y*=B=6A^2\,!0j'Yc'.a.a!"d,'T1\!!$Y:ifA;*q7U"(XbW/g2-K2MQ2gmbd(2WL9T[^B(L?H_VG*Q!(Sh-5!$L'.Jn79#d6>4WZd;pD,S;R.!!!Smb5\:_+,'ds!'lHM#ljr*+UFA6!!!R^?jQf5!$MW6!!!!1Jm\lb!!"/JQ2gmb&;"9r!!!!B#aPGj!"a`i#ljr*+lWYu6gh(uc2Din+!2T;hOa'b99n&"9$)7.,ldoFZsj85F1_=)5JCDCC9csb(0(%Q^Nr'#P-*o-,ldoFcA3JlkDk$U*4>)0YN2eY2:k_r[U(.[!WW3C6L8+Ug&(NAVl(mi-ca9J7n6&jO2ns$/4q*g!WW3C;S6E5PH2M6FV2G&!!!"&Z%M09nb_bjWf.'R!!!#;'0B<.G.<#arI3MK<+aC[f^-$5%VK.25pBD4!!"->r3%&SRTSH/I&B/h:C0.;OO6-/sDJNV:@Mo]o/?E.ge$E-1/R>d]/&!(@T,O;KH"N-oIFg`&6^D&b,ia2`?XN-,gb_rMMRfsoZbPs06*frM.[c04p%EUd[+fW-1:)#&KslrY:kP%bUGaNf4uk4N/$l1bJ)G4Hea.XNRNs0A>b!FI^8J`bB)GZ#A9=6Ih>OejNW5/#9WKKD?u4&d\lWg1R!N%1ISF%m]ht]VEPJEJdc+J(1>08[6]Kd8GU8d#]#KJo!`S>hX7q(]>&d'0bXPZug!Jp=G)URq>eefH3'96J^SeV)E/@sR^?b1^",54-X4SLJjRenf\2$EMX35=hkNHi%)]3_Qn$l\KX]>2;;!3!$rG6%kS*gEWpNGWi-5]CeS0Lb](Clc-SE<\V(Cri\*,Vq`=#ZFe4,044ngfuB3hj?$=,h]rLbXZV3L-_[6]SF6rq>'olJAe>S%ae*jh4.'mM>\L;bF1UFkj#*hVg]&618"5'u`%IIJ67P]X8=ed@s[+1@pOR2GKJnjPM"ugatD&]j`a-=5<(<>>loZ]=C&[[t_/t;eaUUD6S/)bh&NA6Ut4Sd_jpgrZ:ntT2aV-S^R!/0Eu=l6$Kk;o3Fue7ZK"=oI<"?mT,\LH>$(^N%*n\U5hmQ3,cftVE=O#G]%"re!$@>90[4[namDgMX;.b>M7;)^L\FID,?YZb"4YG&qcslgI()Zhf_OA`Gka>Jp,fg$'AWf$^#,Rdf'cZMDLmft!O-5ZA.:B@N!e9m,Q55225VC56FK]BpJ^.7$_;hAi)3e61kGF/@&pH8m]c='Bh2So\pm_D0\DR1oCiR('or]2nGDQCX_qn!]YghT42q/u?MGri+QUG:K__k3V)spSMQCQ'4JG^.>,aVUkT!S&Ln`Sn4tjIPa.C)U'YQR:(,[G-%I=+NLQWE*7T^D72B)kcLCSF)r#h>Hd."A_UsG+4!]hj_5@=,jEaW7qTf2Zbq*V>hV>$j1&#pY'.(S^Am`I:pi6\81BfkZ]cD\-D].kiRu?H4RYs9aX(6L[Eu'_(guG!lq*g8Q[FskkesaG>aj,9Vma^Q=W@PI>Gc/$j42%)>;Btl5fuNLM[o6BV,b7hJb3\79b2HWj9GPIOF&N_sm1m128VtHo]TPVS=t"b.MmRORV-Ft0SfMUQkF+3/Po\/\q>&,j?[o^mq0ok'&?KXfZP1SdH:b^tbI!begRu./r7kgYGsQ.VMh/(b@hX!:l?U(o^3VL!?c=>\_MfZ^%!JHQ3r*N7h$RfKM=iYg%&Wp[tc!6@86LcCPXc=)b:QM@82noG;[XeIZCjJ&OQ>DnS4qVl?Wb\^:%J.dDauDKbAAW1rR)-NS)/B3b5A!T5oqaUeFCm:k+H2t&E$4[\e/M"'+5#1$b'ppKmn;M?]E5+'&X8,:TV*pY#+*9j6&7PL:E"ETMqlTg#sWabpCI@tNRcrab+fI>1M]s5On/RMNfk#!S(H=CIIadkPBfRar]W4')0X?Wp*,aXM'=C(.aouF\0+'qb9#>=[5a3.7>]U:R[.5_Q0"ZD7Lf'7W*/*h60As]E5B'A5R<.^g:DddpchKPNQ<\pGKjn!c<]0'+3/V"`HHCqS?6R@9m(2>NS/RNKn8Lt^+^7qSTFg`76_2;E&I<7::bi-@H=`4J)'C&dR:H-'3G:JXddo\ZQrpgLi_fp=rBB4$/]j_$YJe'@sdg4C`&"!Pdl*<#N*bALP>fbuBgSA"Q\f'1H(g$YW_B,#6,!-9!+M)mEF.:*>,soDEHjM%Kg6_o@'$YTCpUkF8f>g)FLLqV>L'/M^CY*8fX<^:Rcqp2A1p;2Kk\"`r2!!10X"TS^Rs"5$6^tgtHq`h&A_8hXc:^[sNC5\N;amU"E1(]"'VH_uK7sSCRJ[[F/QE3:f7TXn5dS4Z$0b.':+*>QHq/X)2LK2q(;Hb)C4!b)EX@\N[(N^XfdgMihe?6p1dHR>o#Un]s[jm%(eEY+<-"^h8RGG2(Hj8tR[P'b^t1em6GVU2EHRHqP>Y?[h5+p%eQegQ0Jd$2U0P(TuH&1g*RlGk1En5?Jc)[9[8uca;/*'\Xm3C>Gt,j*ngUK4WX$-$@3P=-HN$k'(&DjUn>bcL!W5BIFqVG)+40Qeeq-?G#CdO1LV4ZaFM9XhXu08s?5n0HE@OSKpACKsf<_n*ft1VXHn\BAJOu!QW^^$4FuC-Y3sI`aU*iAI-<7mcT(mcc<\Ba1hm*n9>^;D\Y0lLah8:m/$]PsP`*?rc]>"Q%mkFG1pKm9+%p5S1bL25KHdG*0=-FAr6qc/.hY*U:(KbHms0].u*.=s\-HJCj_-lMsNGNO;[*S++0/j,&V_5H&F+7g^'OqbK*dk>m/<>7Gc"p=u25GN-,-bO#kEEH6,iu>-HZODqL3gFI>2EQNbgEIM?KPV^XuUCQo=`UWjIP.*bsMSINR.>_Fr"BS0"7A,\Zto"C`\kiR[3\3*\W@pbVurggc73U/![Ki)S"h&;o[bkd,F;O\s<#^#;7/MSSS*apUte;!h1t!7Yt5?XUY;6Ypr@OC?]'ZgD[:7F1XC)[_dn`k$01/=Y"Bs%m3s=\[VTR\fp]'&'A9_S]2?H%Sk3q9cX-rJ#;1D#gm3u]!$6RlFr.Q0$,4ZOn6)'h>e,lRB5%iJGX)S*h_fLiC9!PMc]C(@fRrA=A0l)h.T!dLADY+.:\u-B;-U6-&D*$;C"%O<n0eW(RKIN'&Or8eHiFX_;?$'LfuHgC"t=KW,1<(ppu2eSRXU>E<,jn?4qhool=WfsKU*?9Mb(d.7)Wts4:H0Rb3l-1_c^AZtji&4[%NTDf(2d4+j\G%oV`LK*fFh^aE'i,="5.[XTSgs3CF85Q)Q2ctj3TmR2n6iLJc;SJtWb2PA9@_/`,HgRj[--rMkq_-&+f4/n_;U\5NCCLpIHL.1lcoEi1mJ`alg:T[@Hg>.]!JO:XAEuLe/+'lHLuO]h"aO@>Q"EjV`1d7s6-RG[,>,_T,]=r?/g/:TJ(bp1%I_K9b%GW'4]<*;rjQ`H;E!Y(d"c=l`T)<#Xr^6c'=jX`\a:DQn0a&]%sHh]<@Oih]Rc+Res$f01Kl^JG'Y_9"Cni#]sT0F(iuY!mJl[s1EE!Eg1LX\HP=+t=o+kt:QA\(Hk/Lmg\gU@iNC)qUdnfk7b]>+D&f\8daj/&X]Q=7P-`k$%sB&PRJ>jdQZmL'q_XfgVr(ZBHFm-ddPTSgCp5Fs4oNp#Q4W>TZ:-Xe;D!Eim[Wda`qeYP2&hZ@>^QA0;H6iUnlJfLGuoNiEQ(#Bp^?tf^Eendstream +endobj +% 'FormXob.fe5c3814b8ecd593eed8672570be8fc0': class PDFImageXObject +12 0 obj +<< /BitsPerComponent 8 + /ColorSpace /DeviceGray + /Decode [ 0 + 1 ] + /Filter [ /ASCII85Decode + /FlateDecode ] + /Height 550 + /Length 155 + /Subtype /Image + /Type /XObject + /Width 883 >> +stream +Gb"0;0`_7S!5bE.WFlQ&TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!!#WBf&^(XT~>endstream +endobj +% 'Page2': class PDFPage +13 0 obj +% Page dictionary +<< /Contents 26 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 24 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] + /XObject << /FormXob.dff977657d895d2e15b12a22f3b5ae1c 11 0 R >> >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'R14': class PDFCatalog +14 0 obj +% Document Root +<< /Outlines 16 0 R + /PageLabels 27 0 R + /PageMode /UseNone + /Pages 24 0 R + /Type /Catalog >> +endobj +% 'R15': class PDFInfo +15 0 obj +<< /Author () + /CreationDate (D:20131124204335+00'00') + /Creator (\(unspecified\)) + /Keywords () + /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) + /Title () >> +endobj +% 'R16': class PDFOutlines +16 0 obj +<< /Count 7 + /First 17 0 R + /Last 23 0 R + /Type /Outlines >> +endobj +% 'Outline.0': class OutlineEntryObject +17 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 765.0236 + 0 ] + /Next 18 0 R + /Parent 16 0 R + /Title (Chips-2.0 Demo for ATLYS Development Card) >> +endobj +% 'Outline.1': class OutlineEntryObject +18 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 621.0236 + 0 ] + /Next 19 0 R + /Parent 16 0 R + /Prev 17 0 R + /Title (Dependencies) >> +endobj +% 'Outline.2': class OutlineEntryObject +19 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 462.0236 + 0 ] + /Next 20 0 R + /Parent 16 0 R + /Prev 18 0 R + /Title (Install) >> +endobj +% 'Outline.3': class OutlineEntryObject +20 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 341.8236 + 0 ] + /Next 21 0 R + /Parent 16 0 R + /Prev 19 0 R + /Title (Chips Compile) >> +endobj +% 'Outline.4': class OutlineEntryObject +21 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 257.6236 + 0 ] + /Next 22 0 R + /Parent 16 0 R + /Prev 20 0 R + /Title (Build in ISE) >> +endobj +% 'Outline.5': class OutlineEntryObject +22 0 obj +<< /Dest [ 9 0 R + /XYZ + 62.69291 + 161.4236 + 0 ] + /Next 23 0 R + /Parent 16 0 R + /Prev 21 0 R + /Title (Download to ATLYS) >> +endobj +% 'Outline.6': class OutlineEntryObject +23 0 obj +<< /Dest [ 13 0 R + /XYZ + 62.69291 + 707.8236 + 0 ] + /Parent 16 0 R + /Prev 22 0 R + /Title (Setup and Test) >> +endobj +% 'R24': class PDFPages +24 0 obj +% page tree +<< /Count 2 + /Kids [ 9 0 R + 13 0 R ] + /Type /Pages >> +endobj +% 'R25': class PDFStream +25 0 obj +% page stream +<< /Length 6534 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 744.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Chips-2.0 Demo for ATLYS Development Card) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 732.0236 cm +Q +q +1 0 0 1 62.69291 717.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 36.93937 0 Td (Author:) Tj T* -36.93937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Jonathan P Dawson) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 702.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 48.03937 0 Td (Date:) Tj T* -48.03937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (2013-10-15) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 687.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 44.13937 0 Td (email:) Tj T* -44.13937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 .501961 rg +0 0 .501961 RG +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (chips@jondawson.org.uk) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 633.0236 cm +q +BT 1 0 0 1 0 38 Tm 1.129213 Tw 12 TL /F1 10 Tf 0 0 0 rg (This project is intended to demonstrate the capabilities of the ) Tj 0 0 .501961 rg (Chips-2.0 ) Tj 0 0 0 rg (development environment. The) Tj T* 0 Tw 1.883555 Tw (project is targets the Xilinx Spartan 6 device, and more specifically, the Digilent ATLYS development) Tj T* 0 Tw 2.017318 Tw (platform. The demo implements a TCP/IP socket interface, and a simple web application. So far the) Tj T* 0 Tw (demonstration has been tested on a Ubuntu Linux only.) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 600.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Dependencies) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 582.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (You will need:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 576.0236 cm +Q +q +1 0 0 1 62.69291 576.0236 cm +Q +q +1 0 0 1 62.69291 564.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Xilinx ISE 12.0 or later \(webpack edition is free\)) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 558.0236 cm +Q +q +1 0 0 1 62.69291 546.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Python 2.7 or later \(but not Python 3\)) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 540.0236 cm +Q +q +1 0 0 1 62.69291 528.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Chips-2.0 \(Included\)) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 522.0236 cm +Q +q +1 0 0 1 62.69291 510.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Digilent ) Tj 0 0 .501961 rg (ATLYS ) Tj 0 0 0 rg (Spartan 6 Development Kit.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 504.0236 cm +Q +q +1 0 0 1 62.69291 492.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Digilent ADEPT2 ) Tj 0 0 .501961 rg (utility) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 486.0236 cm +Q +q +1 0 0 1 62.69291 474.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (git) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 474.0236 cm +Q +q +1 0 0 1 62.69291 441.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Install) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 423.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Clone the git the repository with git:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 353.8236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 60 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 38 Tm /F3 10 Tf 12 TL ($ git clone git@github.com:dawsonjon/Chips-Demo.git) Tj T* ($ cd Chips-Demo) Tj T* ($ git submodule init) Tj T* ($ git submodule update) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 320.8236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Chips Compile) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 302.8236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (To compile the c code in chips, issue the following command in the project folder:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 269.6236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ ./atlys.py compile) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 236.6236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Build in ISE) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 206.6236 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .177633 Tw (Edit the Xilinx variable in the scripts/user_settings to point to the Xilinx ISE install directory. Then build the) Tj T* 0 Tw (design using the following command:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 173.4236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ ./atlys.py build) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 140.4236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Download to ATLYS) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 122.4236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Power up the ATLYS, and connect the JTAG USB cable to your PC. Run the download command:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 89.22362 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ ./atlys.py download) Tj T* ET +Q +Q +Q +Q +Q + +endstream +endobj +% 'R26': class PDFStream +26 0 obj +% page stream +<< /Length 3566 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 753.0236 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (You can complete all three steps in one go using the ) Tj /F4 10 Tf (all ) Tj /F1 10 Tf (option:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 719.8236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ ./atlys.py all) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 686.8236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Setup and Test) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 545.6236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 132 re B* +Q +q +BT 1 0 0 1 0 110 Tm 12 TL /F3 10 Tf 0 0 0 rg (+----------------+ +----------------+) Tj T* (| PC | | Digilent ATLYS |) Tj T* (| | POWER =======) Tj (>) Tj (o |) Tj T* (| | | |) Tj T* (| USB o) Tj (<) Tj (===============) Tj (>) Tj (o JTAG USB |) Tj T* (| | | |) Tj T* (| ETH0 o) Tj (<) Tj (===============) Tj (>) Tj (o ETHERNET |) Tj T* (| | | |) Tj T* (| 192.168.1.0 | | 192.168.1.1 |) Tj T* (+----------------+ +----------------+) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 513.6236 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.905318 Tw (Connect the Ethernet port to ATLYS, using a crossed over Ethernet cable \(which comes with the) Tj T* 0 Tw (development kit\).) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 483.6236 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.425366 Tw (Using the script, configure Ethernet port with IP address 192.168.1.0 and subnet mask 255.255.255.0.) Tj T* 0 Tw (Turn off TCP Window Scaling and TCP time stamps:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 450.4236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ ./configure_network) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 430.4236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Verify connection using ping command:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 289.2236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 132 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 110 Tm /F3 10 Tf 12 TL ($ ping 192.168.1.1) Tj T* (PING 192.168.1.1 \(192.168.1.1\) 56\(84\) bytes of data.) Tj T* (64 bytes from 192.168.1.1: icmp_req=2 ttl=255 time=0.207 ms) Tj T* (64 bytes from 192.168.1.1: icmp_req=3 ttl=255 time=0.263 ms) Tj T* (64 bytes from 192.168.1.1: icmp_req=4 ttl=255 time=0.124 ms) Tj T* (64 bytes from 192.168.1.1: icmp_req=5 ttl=255 time=0.185 ms) Tj T* (64 bytes from 192.168.1.1: icmp_req=6 ttl=255 time=0.275 ms) Tj T* (--- 192.168.1.1 ping statistics ---) Tj T* (6 packets transmitted, 5 received, 16% packet loss, time 5001ms) Tj T* (rtt min/avg/max/mdev = 0.124/0.210/0.275/0.057 ms) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 269.2236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Connect to 192.168.1.1 using your favourite browser.) Tj T* ET +Q +Q +q +1 0 0 1 191.6778 137.2236 cm +q +211.92 0 0 132 0 0 cm +/FormXob.dff977657d895d2e15b12a22f3b5ae1c Do +Q +Q + +endstream +endobj +% 'R27': class PDFPageLabels +27 0 obj +% Document Root +<< /Nums [ 0 + 28 0 R + 1 + 29 0 R ] >> +endobj +% 'R28': class PDFPageLabel +28 0 obj +% None +<< /S /D + /St 1 >> +endobj +% 'R29': class PDFPageLabel +29 0 obj +% None +<< /S /D + /St 2 >> +endobj +xref +0 30 +0000000000 65535 f +0000000113 00000 n +0000000246 00000 n +0000000411 00000 n +0000000598 00000 n +0000000845 00000 n +0000001100 00000 n +0000001423 00000 n +0000001704 00000 n +0000001863 00000 n +0000002188 00000 n +0000002411 00000 n +0000063493 00000 n +0000063905 00000 n +0000064252 00000 n +0000064411 00000 n +0000064659 00000 n +0000064784 00000 n +0000064985 00000 n +0000065172 00000 n +0000065354 00000 n +0000065542 00000 n +0000065729 00000 n +0000065921 00000 n +0000066080 00000 n +0000066196 00000 n +0000072829 00000 n +0000076498 00000 n +0000076604 00000 n +0000076681 00000 n +trailer +<< /ID + % ReportLab generated PDF document -- digest (http://www.reportlab.com) + [($*@\332/f\303\265\2669d&P\351\3254) ($*@\332/f\303\265\2669d&P\351\3254)] + + /Info 15 0 R + /Root 14 0 R + /Size 30 >> +startxref +76728 +%%EOF Index: COPYING.txt =================================================================== --- COPYING.txt (nonexistent) +++ COPYING.txt (revision 2) @@ -0,0 +1,19 @@ +Copyright (c) 2013 Jonathan P Dawson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Index: TCPIP.rst =================================================================== --- TCPIP.rst (nonexistent) +++ TCPIP.rst (revision 2) @@ -0,0 +1,252 @@ +Chips-2.0 Demo for SP605 Development Card +========================================= + +:Author: Jonathan P Dawson +:Date: 2013-10-17 +:email: chips@jondawson.org.uk + +This project implements a TCP/IP stack. The TCP/IP stack acts as a server, and +can accept a single connection to a TCP port. The connection is provided as a +bidirectional stream of data to the application. The following protocols are supported: + + + ARP request/response (with 16 level cache) + + ICMP echo request/response (ping) + + TCP/IP socket + +Synthesis Estimate +================== + +The TCP/IP server consumes around 800 LUTs and 300 Flip-Flops in a Xilinx Spartan 6 device. + + +Dependencies +============ + +The stack is implemented in C, and needs Chips-2.0 to compile it into a Verilog +module. + +Source Files +============ + +The TCP/IP stack is provided by two source files: + + + source/server.h + + source/server.c + +Configuration +============= + +The following parameters can be configured at compile time within source/server.h: + + + Local Ethernet MAC address + + Local IP Address + + Local TCP Port number + +Compile +======= + +Compile into a Verilog module (server.v) using the following command:: + + $ chip2/c2verilog source/server.v + +Interface +========= + +Ethernet Interface +------------------ + +The Ethernet interface consists of two streams of data: + + + An input, input_eth_rx. + + An output, output_eth_tx. + +Both streams are 16 bits wide, and use the following protocol: + + ++------+-----------------+ +| word | designation | ++------+-----------------+ +| 0 | length in bytes | ++------+-----------------+ +| n | data | ++------+-----------------+ + + +Socket Interface +---------------- + +The socket interface consists of two streams of data: + + + An input, input_socket. + + An output, output_socket. + +Both streams are 16 bits wide, and use the following protocol: + + ++------+-----------------+ +| word | designation | ++------+-----------------+ +| 0 | length in bytes | ++------+-----------------+ +| n | data | ++------+-----------------+ + + +Stream Interconnect Conventions +=============================== + +The main aims of the interface are: + + - To be simple to implement. + - Add little performance/logic overhead. + - Allow designs to grow without adding extra levels of asynchronous logic. + - Easy to interface with standard interconnects. + +:: + + RST >-o-----------------------------+ + CLK >-+-o-------------------------+ | + | | | | + | | +-----------+ | | +--------------+ + | | | TX | | | | RX | + | +---> | | +-----> | + +-----> | +-------> | + | | | | + | | | | + | out >=================> in | + | | _STB | | + | out >-----------------> in | + | | _ACK | | + | in <-----------------< out | + | | | | + +-----------+ +--------------+ + +Global Signals +-------------- + + + ++------+-----------+------+-------------+ +| Name | Direction | Type | Description | ++------+-----------+------+-------------+ +| CLK | input | bit | Clock | ++------+-----------+------+-------------+ +| RST | input | bit | Reset | ++------+-----------+------+-------------+ + + + +Interconnect Signals +-------------------- + + + ++----------------+-----------+------+-----------------------------------------------------------+ +| Name | Direction | Type | Description | ++----------------+-----------+------+-----------------------------------------------------------+ +| | TX to RX | bus | Payload Data | ++----------------+-----------+------+-----------------------------------------------------------+ +| _STB | TX to RX | bit | '1' indicates that payload data is valid and TX is ready. | ++----------------+-----------+------+-----------------------------------------------------------+ +| _ACK | TX to RX | bit | '1' indicates that RX is ready. | ++----------------+-----------+------+-----------------------------------------------------------+ + + + +Interconnect Bus Transaction +---------------------------- + +- Both transmitter and receiver shall be synchronised to the '0' -> '1' transition of CLK. +- If RST is set to '1' upon the '0' -> '1' transition of clock the transmitter shall terminate any active bus transaction and set _STB to '0'. +- If RST is set to '1' upon the '0' -> '1' transition of clock the receiver shall terminate any active bus transaction and set _ACK to '0'. +- If RST is set to '0', normal operation shall commence as follows: +- The transmitter may insert wait states on the bus by setting _STB '0'. +- The transmitter shall set _STB to '1' to signify that data is valid. +- Once _STB has been set to '1', it shall remain at '1' until the transaction completes. +- The transmitter shall ensure that contains valid data for the entire period that _STB is '1'. +- The transmitter may set to any value when _STB is '0'. +- The receiver may insert wait states on the bus by setting _ACK to '0'. +- The receiver shall set _ACK to '1' to signify that it is ready to receive data. +- Once _ACK has been set to '1', it shall remain at '1' until the transaction completes. +- Whenever _STB is '1' and _ACK are '1', a bus transaction shall complete on the following '0' -> '1' transition of CLK. + +:: + + RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ------------------------------------------------ + X VALID X + ----- ------- ------------------------------------------------ + ------- + _STB | | + ----- ------------------------------------------------ + --- + _ACK | | + --------- ------------------------------------------------ + + + ^^^^ RX adds wait states + + ^^^^ Data transfers + + RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ------------------------------------------------ + X VALID X + ----- ------- ------------------------------------------------ + --- + _STB | | + --------- ------------------------------------------------ + ------- + _ACK | | + ----- ------------------------------------------------ + + + ^^^^ TX adds wait states + + ^^^^ Data transfers + +.. + +- Both the transmitter and receiver may commence a new transaction without inserting any wait states. + +:: + + RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ---- ---- -------------------------------------- + X D0 X D1 X D2 X + ----- ------- ---- ---- -------------------------------------- + ------------- + _STB | | + --------- -------------------------------------- + ----------------- + _ACK | | + ----- -------------------------------------- + + ^^^^ TX adds wait states + + ^^^^ Data transfers + + ^^^^ STB and ACK needn't return to 0 between data words + +.. + + +- The receiver may delay a transaction by inserting wait states until the transmitter indicates that data is available. + +- The transmitter shall not delay a transaction by inserting wait states until the receiver is ready to accept data. + +- Deadlock would occur if both the transmitter and receiver delayed a transaction until the other was ready. Index: scripts/atlys.py =================================================================== --- scripts/atlys.py (nonexistent) +++ scripts/atlys.py (revision 2) @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +"""compile, build and download the ATLYS demo to the ATLYS development kit""" + +import sys +import os +import shutil + +from user_settings import xilinx + +current_directory = os.getcwd() +working_directory = "ATLYS" +shutil.copyfile("xilinx_input/ATLYS.ucf", os.path.join(working_directory, "ATLYS.ucf")) +shutil.copyfile("xilinx_input/ATLYS.prj", os.path.join(working_directory, "ATLYS.prj")) +shutil.copyfile("xilinx_input/xst_mixed.opt", os.path.join(working_directory, "xst_mixed.opt")) +shutil.copyfile("xilinx_input/balanced.opt", os.path.join(working_directory, "balanced.opt")) +shutil.copyfile("xilinx_input/bitgen.opt", os.path.join(working_directory, "bitgen.opt")) +os.chdir(working_directory) + +if "compile" in sys.argv or "all" in sys.argv: + print "Compiling C files using chips ...." + retval = os.system("../chips2/c2verilog ../source/user_design_atlys.c") + retval = os.system("../chips2/c2verilog ../source/server.c") + if retval != 0: + sys.exit(-1) + +if "build" in sys.argv or "all" in sys.argv: + print "Building Demo using Xilinx ise ...." + retval = os.system("%s/xflow -synth xst_mixed.opt -p XC6Slx45-CSG324 -implement balanced.opt -config bitgen.opt ATLYS"%xilinx) + if retval != 0: + sys.exit(-1) + +if "download" in sys.argv or "all" in sys.argv: + print "Downloading bit file to development kit ...." + retval = os.system("sudo djtgcfg prog -d Atlys -i 0 -f ATLYS.bit") + if retval != 0: + sys.exit(-1) + +os.chdir(current_directory)

scripts/atlys.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: scripts/sp605.py =================================================================== --- scripts/sp605.py (nonexistent) +++ scripts/sp605.py (revision 2) @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +"""compile, build and download the SP605 demo to the SP605 development kit""" + +import sys +import os +import shutil + +from user_settings import xilinx + +current_directory = os.getcwd() +working_directory = "SP605" +shutil.copyfile("xilinx_input/SP605.ucf", os.path.join(working_directory, "SP605.ucf")) +shutil.copyfile("xilinx_input/SP605.prj", os.path.join(working_directory, "SP605.prj")) +shutil.copyfile("xilinx_input/xst_mixed.opt", os.path.join(working_directory, "xst_mixed.opt")) +shutil.copyfile("xilinx_input/balanced.opt", os.path.join(working_directory, "balanced.opt")) +shutil.copyfile("xilinx_input/bitgen.opt", os.path.join(working_directory, "bitgen.opt")) +os.chdir(working_directory) + +if "compile" in sys.argv or "all" in sys.argv: + print "Compiling C files using chips ...." + retval = os.system("../chips2/c2verilog no_reuse ../source/user_design_sp605.c") + retval = os.system("../chips2/c2verilog no_reuse ../source/server.c") + if retval != 0: + sys.exit(-1) + +if "build" in sys.argv or "all" in sys.argv: + print "Building Demo using Xilinx ise ...." + retval = os.system("%s/xflow -synth xst_mixed.opt -p XC6Slx45t-fgg484 -implement balanced.opt -config bitgen.opt SP605"%xilinx) + if retval != 0: + sys.exit(-1) + +if "download" in sys.argv or "all" in sys.argv: + print "Downloading bit file to development kit ...." + command_file = open("download.cmd", 'w') + command_file.write("setmode -bscan\n") + command_file.write("setCable -p auto\n") + command_file.write("identify\n") + command_file.write("assignfile -p 2 -file SP605.bit\n") + command_file.write("program -p 2\n") + command_file.write("quit\n") + command_file.close() + retval = os.system("%s/impact -batch download.cmd"%xilinx) + if retval != 0: + sys.exit(-1) + +os.chdir(current_directory)
scripts/sp605.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: scripts/user_settings.py =================================================================== --- scripts/user_settings.py (nonexistent) +++ scripts/user_settings.py (revision 2) @@ -0,0 +1 @@ +xilinx = "/media/sdb1/Xilinx/14.3/14.3/ISE_DS/ISE/bin/lin64" Index: scripts/configure_network =================================================================== --- scripts/configure_network (nonexistent) +++ scripts/configure_network (revision 2) @@ -0,0 +1,6 @@ +sudo ifconfig eth0 192.168.1.0 netmask 255.255.255.0 +#sudo arp -s 192.168.1.1 hw_addr 00:01:02:03:04:05 +#ping -c 3 192.168.1.1 +sudo sysctl -w net.ipv4.tcp_window_scaling=0 +sudo sysctl -w net.ipv4.tcp_timestamps=0 +#scripts/send_tcp.py
scripts/configure_network Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: TCPIP.pdf =================================================================== --- TCPIP.pdf (nonexistent) +++ TCPIP.pdf (revision 2) @@ -0,0 +1,2103 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +% 'BasicFonts': class PDFDictionary +1 0 obj +% The standard fonts dictionary +<< /F1 2 0 R + /F2 3 0 R + /F3 5 0 R >> +endobj +% 'F1': class PDFType1Font +2 0 obj +% Font Helvetica +<< /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font >> +endobj +% 'F2': class PDFType1Font +3 0 obj +% Font Helvetica-Bold +<< /BaseFont /Helvetica-Bold + /Encoding /WinAnsiEncoding + /Name /F2 + /Subtype /Type1 + /Type /Font >> +endobj +% 'Annot.NUMBER1': class PDFDictionary +4 0 obj +<< /A << /S /URI + /Type /Action + /URI (mailto:chips@jondawson.org.uk) >> + /Border [ 0 + 0 + 0 ] + /Rect [ 153.7323 + 690.7736 + 526.5827 + 702.7736 ] + /Subtype /Link + /Type /Annot >> +endobj +% 'F3': class PDFType1Font +5 0 obj +% Font Courier +<< /BaseFont /Courier + /Encoding /WinAnsiEncoding + /Name /F3 + /Subtype /Type1 + /Type /Font >> +endobj +% 'Page1': class PDFPage +6 0 obj +% Page dictionary +<< /Annots [ 4 0 R ] + /Contents 27 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 26 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'Page2': class PDFPage +7 0 obj +% Page dictionary +<< /Contents 28 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 26 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'Page3': class PDFPage +8 0 obj +% Page dictionary +<< /Contents 29 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 26 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'Page4': class PDFPage +9 0 obj +% Page dictionary +<< /Contents 30 0 R + /MediaBox [ 0 + 0 + 595.2756 + 841.8898 ] + /Parent 26 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'R10': class PDFCatalog +10 0 obj +% Document Root +<< /Outlines 12 0 R + /PageLabels 31 0 R + /PageMode /UseNone + /Pages 26 0 R + /Type /Catalog >> +endobj +% 'R11': class PDFInfo +11 0 obj +<< /Author () + /CreationDate (D:20131124204346+00'00') + /Creator (\(unspecified\)) + /Keywords () + /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) + /Title () >> +endobj +% 'R12': class PDFOutlines +12 0 obj +<< /Count 15 + /First 13 0 R + /Last 22 0 R + /Type /Outlines >> +endobj +% 'Outline.0': class OutlineEntryObject +13 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 765.0236 + 0 ] + /Next 14 0 R + /Parent 12 0 R + /Title (Chips-2.0 Demo for SP605 Development Card) >> +endobj +% 'Outline.1': class OutlineEntryObject +14 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 573.0236 + 0 ] + /Next 15 0 R + /Parent 12 0 R + /Prev 13 0 R + /Title (Synthesis Estimate) >> +endobj +% 'Outline.2': class OutlineEntryObject +15 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 522.0236 + 0 ] + /Next 16 0 R + /Parent 12 0 R + /Prev 14 0 R + /Title (Dependencies) >> +endobj +% 'Outline.3': class OutlineEntryObject +16 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 471.0236 + 0 ] + /Next 17 0 R + /Parent 12 0 R + /Prev 15 0 R + /Title (Source Files) >> +endobj +% 'Outline.4': class OutlineEntryObject +17 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 378.0236 + 0 ] + /Next 18 0 R + /Parent 12 0 R + /Prev 16 0 R + /Title (Configuration) >> +endobj +% 'Outline.5': class OutlineEntryObject +18 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 267.0236 + 0 ] + /Next 19 0 R + /Parent 12 0 R + /Prev 17 0 R + /Title (Compile) >> +endobj +% 'Outline.6': class OutlineEntryObject +19 0 obj +<< /Count 2 + /Dest [ 6 0 R + /XYZ + 62.69291 + 182.8236 + 0 ] + /First 20 0 R + /Last 21 0 R + /Next 22 0 R + /Parent 12 0 R + /Prev 18 0 R + /Title (Interface) >> +endobj +% 'Outline.14.0': class OutlineEntryObject +20 0 obj +<< /Dest [ 6 0 R + /XYZ + 62.69291 + 149.8236 + 0 ] + /Next 21 0 R + /Parent 19 0 R + /Title (Ethernet Interface) >> +endobj +% 'Outline.14.1': class OutlineEntryObject +21 0 obj +<< /Dest [ 7 0 R + /XYZ + 62.69291 + 639.0236 + 0 ] + /Parent 19 0 R + /Prev 20 0 R + /Title (Socket Interface) >> +endobj +% 'Outline.7': class OutlineEntryObject +22 0 obj +<< /Count 3 + /Dest [ 7 0 R + /XYZ + 62.69291 + 471.0236 + 0 ] + /First 23 0 R + /Last 25 0 R + /Parent 12 0 R + /Prev 19 0 R + /Title (Stream Interconnect Conventions) >> +endobj +% 'Outline.15.0': class OutlineEntryObject +23 0 obj +<< /Dest [ 7 0 R + /XYZ + 62.69291 + 128.8236 + 0 ] + /Next 24 0 R + /Parent 22 0 R + /Title (Global Signals) >> +endobj +% 'Outline.15.1': class OutlineEntryObject +24 0 obj +<< /Dest [ 8 0 R + /XYZ + 62.69291 + 717.0236 + 0 ] + /Next 25 0 R + /Parent 22 0 R + /Prev 23 0 R + /Title (Interconnect Signals) >> +endobj +% 'Outline.15.2': class OutlineEntryObject +25 0 obj +<< /Dest [ 8 0 R + /XYZ + 62.69291 + 603.0236 + 0 ] + /Parent 22 0 R + /Prev 24 0 R + /Title (Interconnect Bus Transaction) >> +endobj +% 'R26': class PDFPages +26 0 obj +% page tree +<< /Count 4 + /Kids [ 6 0 R + 7 0 R + 8 0 R + 9 0 R ] + /Type /Pages >> +endobj +% 'R27': class PDFStream +27 0 obj +% page stream +<< /Length 6815 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 744.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Chips-2.0 Demo for SP605 Development Card) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 732.0236 cm +Q +q +1 0 0 1 62.69291 717.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 36.93937 0 Td (Author:) Tj T* -36.93937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Jonathan P Dawson) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 702.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 48.03937 0 Td (Date:) Tj T* -48.03937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (2013-10-17) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 687.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 44.13937 0 Td (email:) Tj T* -44.13937 0 Td ET +Q +Q +q +1 0 0 1 91.03937 3 cm +q +0 0 .501961 rg +0 0 .501961 RG +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (chips@jondawson.org.uk) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 645.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 1.584692 Tw (This project implements a TCP/IP stack. The TCP/IP stack acts as a server, and can accept a single) Tj T* 0 Tw .502927 Tw (connection to a TCP port. The connection is provided as a bidirectional stream of data to the application.) Tj T* 0 Tw (The following protocols are supported:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 639.0236 cm +Q +q +1 0 0 1 62.69291 585.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 48 cm +Q +q +1 0 0 1 20 48 cm +Q +q +1 0 0 1 20 36 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (ARP request/response \(with 16 level cache\)) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (ICMP echo request/response \(ping\)) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (TCP/IP socket) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 585.0236 cm +Q +q +1 0 0 1 62.69291 552.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Synthesis Estimate) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 534.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The TCP/IP server consumes around 800 LUTs and 300 Flip-Flops in a Xilinx Spartan 6 device.) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 501.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Dependencies) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 483.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The stack is implemented in C, and needs Chips-2.0 to compile it into a Verilog module.) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 450.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Source Files) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 432.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The TCP/IP stack is provided by two source files:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 426.0236 cm +Q +q +1 0 0 1 62.69291 390.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (source/server.h) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (source/server.c) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 390.0236 cm +Q +q +1 0 0 1 62.69291 357.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Configuration) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 339.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The following parameters can be configured at compile time within source/server.h:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 333.0236 cm +Q +q +1 0 0 1 62.69291 279.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 48 cm +Q +q +1 0 0 1 20 48 cm +Q +q +1 0 0 1 20 36 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Local Ethernet MAC address) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Local IP Address) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Local TCP Port number) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 279.0236 cm +Q +q +1 0 0 1 62.69291 246.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Compile) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 228.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Compile into a Verilog module \(server.v\) using the following command:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 194.8236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 24 re B* +Q +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL ($ chip2/c2verilog source/server.v) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 161.8236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Interface) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 131.8236 cm +q +BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Ethernet Interface) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 113.8236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The Ethernet interface consists of two streams of data:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 107.8236 cm +Q + +endstream +endobj +% 'R28': class PDFStream +28 0 obj +% page stream +<< /Length 8532 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 729.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (An input, input_eth_rx.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (An output, output_eth_tx.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 729.0236 cm +Q +q +1 0 0 1 62.69291 711.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Both streams are 16 bits wide, and use the following protocol:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 705.0236 cm +Q +q +1 0 0 1 62.69291 651.0236 cm +1 1 1 rg +n 0 54 469.8898 -18 re f* +.878431 .878431 .878431 rg +n 0 36 469.8898 -18 re f* +1 1 1 rg +n 0 18 469.8898 -18 re f* +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (word) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (designation) Tj T* ET +Q +Q +q +1 0 0 1 6 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (0) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (length in bytes) Tj T* ET +Q +Q +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (n) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (data) Tj T* ET +Q +Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 36 m 469.8898 36 l S +n 0 18 m 469.8898 18 l S +n 122.5799 0 m 122.5799 54 l S +n 0 54 m 469.8898 54 l S +n 0 0 m 469.8898 0 l S +n 0 0 m 0 54 l S +n 469.8898 0 m 469.8898 54 l S +Q +Q +q +1 0 0 1 62.69291 651.0236 cm +Q +q +1 0 0 1 62.69291 621.0236 cm +q +BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Socket Interface) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 603.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The socket interface consists of two streams of data:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 597.0236 cm +Q +q +1 0 0 1 62.69291 561.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (An input, input_socket.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (An output, output_socket.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 561.0236 cm +Q +q +1 0 0 1 62.69291 543.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Both streams are 16 bits wide, and use the following protocol:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 537.0236 cm +Q +q +1 0 0 1 62.69291 483.0236 cm +1 1 1 rg +n 0 54 469.8898 -18 re f* +.878431 .878431 .878431 rg +n 0 36 469.8898 -18 re f* +1 1 1 rg +n 0 18 469.8898 -18 re f* +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (word) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (designation) Tj T* ET +Q +Q +q +1 0 0 1 6 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (0) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (length in bytes) Tj T* ET +Q +Q +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (n) Tj T* ET +Q +Q +q +1 0 0 1 128.5799 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (data) Tj T* ET +Q +Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 36 m 469.8898 36 l S +n 0 18 m 469.8898 18 l S +n 122.5799 0 m 122.5799 54 l S +n 0 54 m 469.8898 54 l S +n 0 0 m 469.8898 0 l S +n 0 0 m 0 54 l S +n 469.8898 0 m 469.8898 54 l S +Q +Q +q +1 0 0 1 62.69291 483.0236 cm +Q +q +1 0 0 1 62.69291 450.0236 cm +q +BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Stream Interconnect Conventions) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 432.0236 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The main aims of the interface are:) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 426.0236 cm +Q +q +1 0 0 1 62.69291 354.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +BT 1 0 0 1 0 2 Tm T* ET +q +1 0 0 1 20 66 cm +Q +q +1 0 0 1 20 66 cm +Q +q +1 0 0 1 20 54 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (To be simple to implement.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 48 cm +Q +q +1 0 0 1 20 36 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Add little performance/logic overhead.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 30 cm +Q +q +1 0 0 1 20 18 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Allow designs to grow without adding extra levels of asynchronous logic.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 12 cm +Q +q +1 0 0 1 20 0 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Easy to interface with standard interconnects.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 20 0 cm +Q +q +Q +Q +q +1 0 0 1 62.69291 354.0236 cm +Q +q +1 0 0 1 62.69291 140.8236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 468.6898 204 re B* +Q +q +BT 1 0 0 1 0 182 Tm 12 TL /F3 10 Tf 0 0 0 rg (RST ) Tj (>) Tj (-o-----------------------------+) Tj T* (CLK ) Tj (>) Tj (-+-o-------------------------+ |) Tj T* ( | | | |) Tj T* ( | | +-----------+ | | +--------------+) Tj T* ( | | | TX | | | | RX |) Tj T* ( | +---) Tj (>) Tj ( | | +-----) Tj (>) Tj ( |) Tj T* ( +-----) Tj (>) Tj ( | +-------) Tj (>) Tj ( |) Tj T* ( | | | |) Tj T* ( | | ) Tj (<) Tj (BUS_NAME) Tj (>) Tj ( | |) Tj T* ( | out ) Tj (>) Tj (=================) Tj (>) Tj ( in |) Tj T* ( | | ) Tj (<) Tj (BUS_NAME) Tj (>) Tj (_STB | |) Tj T* ( | out ) Tj (>) Tj (-----------------) Tj (>) Tj ( in |) Tj T* ( | | ) Tj (<) Tj (BUS_NAME) Tj (>) Tj (_ACK | |) Tj T* ( | in ) Tj (<) Tj (-----------------) Tj (<) Tj ( out |) Tj T* ( | | | |) Tj T* ( +-----------+ +--------------+) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 110.8236 cm +q +BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Global Signals) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 98.82362 cm +Q +q +1 0 0 1 62.69291 80.82362 cm +1 1 1 rg +n 0 18 469.8898 -18 re f* +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Name) Tj T* ET +Q +Q +q +1 0 0 1 84.31496 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Direction) Tj T* ET +Q +Q +q +1 0 0 1 227.8924 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Type) Tj T* ET +Q +Q +q +1 0 0 1 306.2073 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Description) Tj T* ET +Q +Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 0 m 469.8898 0 l S +n 78.31496 0 m 78.31496 18 l S +n 221.8924 0 m 221.8924 18 l S +n 300.2073 0 m 300.2073 18 l S +n 0 18 m 469.8898 18 l S +n 0 0 m 0 18 l S +n 469.8898 0 m 469.8898 18 l S +Q +Q + +endstream +endobj +% 'R29': class PDFStream +29 0 obj +% page stream +<< /Length 10789 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 729.0236 cm +1 1 1 rg +n 0 36 469.8898 -18 re f* +.878431 .878431 .878431 rg +n 0 18 469.8898 -18 re f* +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (CLK) Tj T* ET +Q +Q +q +1 0 0 1 84.31496 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (input) Tj T* ET +Q +Q +q +1 0 0 1 227.8924 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bit) Tj T* ET +Q +Q +q +1 0 0 1 306.2073 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Clock) Tj T* ET +Q +Q +q +1 0 0 1 6 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (RST) Tj T* ET +Q +Q +q +1 0 0 1 84.31496 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (input) Tj T* ET +Q +Q +q +1 0 0 1 227.8924 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bit) Tj T* ET +Q +Q +q +1 0 0 1 306.2073 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Reset) Tj T* ET +Q +Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 36 m 469.8898 36 l S +n 0 18 m 469.8898 18 l S +n 78.31496 0 m 78.31496 36 l S +n 221.8924 0 m 221.8924 36 l S +n 300.2073 0 m 300.2073 36 l S +n 0 0 m 0 36 l S +n 469.8898 0 m 469.8898 36 l S +n 0 0 m 469.8898 0 l S +Q +Q +q +1 0 0 1 62.69291 729.0236 cm +Q +q +1 0 0 1 62.69291 699.0236 cm +q +BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Interconnect Signals) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 687.0236 cm +Q +q +1 0 0 1 62.69291 615.0236 cm +1 1 1 rg +n 0 72 469.8898 -18 re f* +.878431 .878431 .878431 rg +n 0 54 469.8898 -18 re f* +1 1 1 rg +n 0 36 469.8898 -18 re f* +.878431 .878431 .878431 rg +n 0 18 469.8898 -18 re f* +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 57 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Name) Tj T* ET +Q +Q +q +1 0 0 1 87.71996 57 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Direction) Tj T* ET +Q +Q +q +1 0 0 1 143.9024 57 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Type) Tj T* ET +Q +Q +q +1 0 0 1 174.5474 57 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Description) Tj T* ET +Q +Q +q +1 0 0 1 6 39 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (<) Tj (BUS_NAME) Tj (>) Tj T* ET +Q +Q +q +1 0 0 1 87.71996 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (TX to RX) Tj T* ET +Q +Q +q +1 0 0 1 143.9024 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bus) Tj T* ET +Q +Q +q +1 0 0 1 174.5474 39 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Payload Data) Tj T* ET +Q +Q +q +1 0 0 1 6 21 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (<) Tj (BUS_NAME) Tj (>) Tj (_STB) Tj T* ET +Q +Q +q +1 0 0 1 87.71996 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (TX to RX) Tj T* ET +Q +Q +q +1 0 0 1 143.9024 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bit) Tj T* ET +Q +Q +q +1 0 0 1 174.5474 21 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL ('1' indicates that payload data is valid and TX is ready.) Tj T* ET +Q +Q +q +1 0 0 1 6 3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (<) Tj (BUS_NAME) Tj (>) Tj (_ACK) Tj T* ET +Q +Q +q +1 0 0 1 87.71996 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (TX to RX) Tj T* ET +Q +Q +q +1 0 0 1 143.9024 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bit) Tj T* ET +Q +Q +q +1 0 0 1 174.5474 3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL ('1' indicates that RX is ready.) Tj T* ET +Q +Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 54 m 469.8898 54 l S +n 0 36 m 469.8898 36 l S +n 0 18 m 469.8898 18 l S +n 81.71996 0 m 81.71996 72 l S +n 137.9024 0 m 137.9024 72 l S +n 168.5474 0 m 168.5474 72 l S +n 0 72 m 469.8898 72 l S +n 0 0 m 469.8898 0 l S +n 0 0 m 0 72 l S +n 469.8898 0 m 469.8898 72 l S +Q +Q +q +1 0 0 1 62.69291 615.0236 cm +Q +q +1 0 0 1 62.69291 585.0236 cm +q +BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Interconnect Bus Transaction) Tj T* ET +Q +Q +q +1 0 0 1 62.69291 573.0236 cm +Q +q +1 0 0 1 62.69291 573.0236 cm +Q +q +1 0 0 1 62.69291 561.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Both transmitter and receiver shall be synchronised to the '0' -) Tj (> '1' transition of CLK.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 555.0236 cm +Q +q +1 0 0 1 62.69291 531.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 14 Tm .497988 Tw 12 TL /F1 10 Tf 0 0 0 rg (If RST is set to '1' upon the '0' -) Tj (> '1' transition of clock the transmitter shall terminate any active bus) Tj T* 0 Tw (transaction and set <) Tj (BUS_NAME) Tj (>) Tj (_STB to '0'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 525.0236 cm +Q +q +1 0 0 1 62.69291 501.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 14 Tm 1.081488 Tw 12 TL /F1 10 Tf 0 0 0 rg (If RST is set to '1' upon the '0' -) Tj (> '1' transition of clock the receiver shall terminate any active bus) Tj T* 0 Tw (transaction and set <) Tj (BUS_NAME) Tj (>) Tj (_ACK to '0'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 495.0236 cm +Q +q +1 0 0 1 62.69291 483.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (If RST is set to '0', normal operation shall commence as follows:) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 477.0236 cm +Q +q +1 0 0 1 62.69291 465.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The transmitter may insert wait states on the bus by setting <) Tj (BUS_NAME) Tj (>) Tj (_STB '0'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 459.0236 cm +Q +q +1 0 0 1 62.69291 447.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The transmitter shall set <) Tj (BUS_NAME) Tj (>) Tj (_STB to '1' to signify that data is valid.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 441.0236 cm +Q +q +1 0 0 1 62.69291 429.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Once <) Tj (BUS_NAME) Tj (>) Tj (_STB has been set to '1', it shall remain at '1' until the transaction completes.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 423.0236 cm +Q +q +1 0 0 1 62.69291 399.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 14 Tm 3.036905 Tw 12 TL /F1 10 Tf 0 0 0 rg (The transmitter shall ensure that <) Tj (BUS_NAME) Tj (> contains valid data for the entire period that) Tj T* 0 Tw (<) Tj (BUS_NAME) Tj (>) Tj (_STB is '1'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 393.0236 cm +Q +q +1 0 0 1 62.69291 381.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The transmitter may set <) Tj (BUS_NAME) Tj (> to any value when <) Tj (BUS_NAME) Tj (>) Tj (_STB is '0'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 375.0236 cm +Q +q +1 0 0 1 62.69291 363.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The receiver may insert wait states on the bus by setting <) Tj (BUS_NAME) Tj (>) Tj (_ACK to '0'.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 357.0236 cm +Q +q +1 0 0 1 62.69291 345.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The receiver shall set <) Tj (BUS_NAME) Tj (>) Tj (_ACK to '1' to signify that it is ready to receive data.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 339.0236 cm +Q +q +1 0 0 1 62.69291 327.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Once <) Tj (BUS_NAME) Tj (>) Tj (_ACK has been set to '1', it shall remain at '1' until the transaction completes.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 321.0236 cm +Q +q +1 0 0 1 62.69291 297.0236 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +BT 1 0 0 1 0 14 Tm 3.199069 Tw 12 TL /F1 10 Tf 0 0 0 rg (Whenever <) Tj (BUS_NAME) Tj (>) Tj (_STB is '1' and <) Tj (BUS_NAME) Tj (>) Tj (_ACK are '1', a bus transaction shall) Tj T* 0 Tw (complete on the following '0' -) Tj (> '1' transition of CLK.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 297.0236 cm +Q +q +1 0 0 1 62.69291 91.11439 cm +q +q +.96447 0 0 .96447 0 0 cm +q +1 0 0 1 6.6 6.843137 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 486 204 re B* +Q +q +BT 1 0 0 1 0 182 Tm 12 TL /F3 10 Tf 0 0 0 rg (RST) Tj T* ( --------------------------------------------------------------) Tj T* ( - - - - - - - - - - - - - - -) Tj T* ( CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |) Tj T* ( - - - - - - - - - - - - - - - -) Tj T* T* ( ----- ------- ------------------------------------------------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj ( X VALID X) Tj T* ( ----- ------- ------------------------------------------------) Tj T* ( -------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_STB | |) Tj T* ( ----- ------------------------------------------------) Tj T* ( ---) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_ACK | |) Tj T* ( --------- ------------------------------------------------) Tj T* T* ET +Q +Q +Q +Q +Q + +endstream +endobj +% 'R30': class PDFStream +30 0 obj +% page stream +<< /Length 4895 >> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 62.69291 462.9516 cm +q +q +.96447 0 0 .96447 0 0 cm +q +1 0 0 1 6.6 6.843137 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 486 312 re B* +Q +q +BT 1 0 0 1 0 290 Tm 12 TL /F3 10 Tf 0 0 0 rg T* ( ^^^^ RX adds wait states) Tj T* T* ( ^^^^ Data transfers) Tj T* T* (RST) Tj T* ( --------------------------------------------------------------) Tj T* ( - - - - - - - - - - - - - - -) Tj T* ( CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |) Tj T* ( - - - - - - - - - - - - - - - -) Tj T* T* ( ----- ------- ------------------------------------------------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj ( X VALID X) Tj T* ( ----- ------- ------------------------------------------------) Tj T* ( ---) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_STB | |) Tj T* ( --------- ------------------------------------------------) Tj T* ( -------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_ACK | |) Tj T* ( ----- ------------------------------------------------) Tj T* T* T* ( ^^^^ TX adds wait states) Tj T* T* ( ^^^^ Data transfers) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 448.9516 cm +Q +q +1 0 0 1 62.69291 448.9516 cm +Q +q +1 0 0 1 62.69291 436.9516 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Both the transmitter and receiver may commence a new transaction without inserting any wait states.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 436.9516 cm +Q +q +1 0 0 1 62.69291 198.6952 cm +q +q +.868237 0 0 .868237 0 0 cm +q +1 0 0 1 6.6 7.601613 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .862745 rg +n -6 -6 540 264 re B* +Q +q +BT 1 0 0 1 0 242 Tm 12 TL /F3 10 Tf 0 0 0 rg (RST) Tj T* ( --------------------------------------------------------------) Tj T* ( - - - - - - - - - - - - - - -) Tj T* ( CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |) Tj T* ( - - - - - - - - - - - - - - - -) Tj T* T* ( ----- ------- ---- ---- --------------------------------------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj ( X D0 X D1 X D2 X) Tj T* ( ----- ------- ---- ---- --------------------------------------) Tj T* ( -------------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_STB | |) Tj T* ( --------- --------------------------------------) Tj T* ( -----------------) Tj T* (<) Tj (BUS_NAME) Tj (>) Tj (_ACK | |) Tj T* ( ----- --------------------------------------) Tj T* T* ( ^^^^ TX adds wait states) Tj T* T* ( ^^^^ Data transfers) Tj T* T* ( ^^^^ STB and ACK needn't return to 0 between data words) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 62.69291 184.6952 cm +Q +q +1 0 0 1 62.69291 184.6952 cm +Q +q +1 0 0 1 62.69291 160.6952 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .483984 Tw (The receiver may delay a transaction by inserting wait states until the transmitter indicates that data) Tj T* 0 Tw (is available.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 154.6952 cm +Q +q +1 0 0 1 62.69291 130.6952 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.496235 Tw (The transmitter shall not delay a transaction by inserting wait states until the receiver is ready to) Tj T* 0 Tw (accept data.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 124.6952 cm +Q +q +1 0 0 1 62.69291 100.6952 cm +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q +1 0 0 1 6 9 cm +q +0 0 0 rg +BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET +Q +Q +q +1 0 0 1 23 -3 cm +q +0 0 0 rg +BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .853984 Tw (Deadlock would occur if both the transmitter and receiver delayed a transaction until the other was) Tj T* 0 Tw (ready.) Tj T* ET +Q +Q +q +Q +Q +q +1 0 0 1 62.69291 100.6952 cm +Q + +endstream +endobj +% 'R31': class PDFPageLabels +31 0 obj +% Document Root +<< /Nums [ 0 + 32 0 R + 1 + 33 0 R + 2 + 34 0 R + 3 + 35 0 R ] >> +endobj +% 'R32': class PDFPageLabel +32 0 obj +% None +<< /S /D + /St 1 >> +endobj +% 'R33': class PDFPageLabel +33 0 obj +% None +<< /S /D + /St 2 >> +endobj +% 'R34': class PDFPageLabel +34 0 obj +% None +<< /S /D + /St 3 >> +endobj +% 'R35': class PDFPageLabel +35 0 obj +% None +<< /S /D + /St 4 >> +endobj +xref +0 36 +0000000000 65535 f +0000000113 00000 n +0000000233 00000 n +0000000398 00000 n +0000000585 00000 n +0000000820 00000 n +0000000979 00000 n +0000001278 00000 n +0000001557 00000 n +0000001836 00000 n +0000002116 00000 n +0000002275 00000 n +0000002523 00000 n +0000002649 00000 n +0000002850 00000 n +0000003043 00000 n +0000003230 00000 n +0000003417 00000 n +0000003605 00000 n +0000003787 00000 n +0000004016 00000 n +0000004197 00000 n +0000004373 00000 n +0000004609 00000 n +0000004786 00000 n +0000004984 00000 n +0000005156 00000 n +0000005287 00000 n +0000012201 00000 n +0000020832 00000 n +0000031721 00000 n +0000036719 00000 n +0000036851 00000 n +0000036928 00000 n +0000037005 00000 n +0000037082 00000 n +trailer +<< /ID + % ReportLab generated PDF document -- digest (http://www.reportlab.com) + [(\367\340\313\223\276>\264\240\026\027\213\340\005q39) (\367\340\313\223\276>\264\240\026\027\213\340\005q39)] + + /Info 11 0 R + /Root 10 0 R + /Size 36 >> +startxref +37129 +%%EOF Index: chips2/documents/compiler.rst =================================================================== --- chips2/documents/compiler.rst (nonexistent) +++ chips2/documents/compiler.rst (revision 2) @@ -0,0 +1,139 @@ +C2VHDL +====== + +C2VHDL converts a subset of the C language into Verilog. + +The project aims to provide: + + - A simpler, higher level alternative to VHDL and VERILOG. + - A useful C subset which maps well onto FPGA devices. + - A very simple implementation which is easy to modify maintain and distribute. + - A fast and flexible verification environment using C. + +Running existing C programs in FPGAs is not a primary objective. + +Note: + +C2VHDL was designed to target the VHDL language, but this branch outputs code to verilog. + +What it Does +============ + +C2VHDL implements a decent subset of C, enough to do useful things in an FPGA: + + - most statements: if, while, for, break, continue, return, switch, case, default + - functions + - single dimension arrays + - c style comments + - c++ style comments + - contstant folding + - dead code removal + - instruction level concurrency + +What it Doesn't +=============== + +C2VHDL doesn't implement these thing that either don't work well in FPGAs, or that +I just haven't been implemented yet: + + - no libc + - no float or double + - no recursion + - no pointers + - no goto statement + - no forward declarations + - no struct + - no union + +Download +======== + +Python script: `c2vhdl.py`_. + +.. _`c2vhdl.py` : https://github.com/downloads/dawsonjon/C2VHDL/c2vhdl.py + +Installation +============= + +1. First `install Python`_. You need *Python* 2.3 or later, but not *Python* 3. +2. Place c2vhdl.py somwhere in your execution path, or execute locally. +3. Thats it! You can now run c2vhdl.py + +.. _`install Python` : http://python.org/download + +How to use it +============= + +Each C file is implemented as a Verilog component that can be used in a design. + +Execution Model +--------------- + +When a design is reset, execution starts with the last function defined in +the C file. This need not be called *main*. The name of the last function +will be used as the name for the generated Verilog component. The C program will +appear to execute in sequence, although the compiler will execute instructions +concurrently if it does not affect the outcome of the program. This will allow +your program to take advantage of the inherent parallelism present in a hardware +design. + +Of course if you want even more parallelism, you can have many C2VHDL +components in your device at the same time. + +Adding Inputs and Outputs +------------------------- + +If you want to add an input or an output to your Verilog component, you can achieve +this by calling functions with *special* names:: + + int temp; + temp = input_spam() //reads from an input called spam + temp = input_eggs() //reads from an input called eggs + output_fish(temp) //writes to an output called fish + +Reading or writing from inputs and outputs causes program execution to block +until data is available. This syncronises data tranfers with other components +executing in the same device, this method of passing data beween concurrent +processes is much simpler than the mutex/lock/semaphore mechanisms used in +multithreaded applications. + +If you don't want to commit yourself to reading and input and blocking +execution, you can check if data is ready:: + + int temp; + if(ready_spam()){ + temp = input_spam() + } + +There is no equivilent function to check if an output is ready to recieve data, +this could cause deadlocks if both the sending and receiving end were waiting +for one another. + +Debugging +--------- + +Since the language is a subset of C, you can use the usual C based tools for +debugging. If you want to know what is going on in a Verilog simulation, you can +use these builtin debug functions:: + + assert(0); //This will fail + assert(a == 12); //This will fail if a is not 12 + report(1); //This will cause the simulator to print 1 + report(temp); //This will cause the simulator to print the value of temp + +Command Line Usage +------------------ + +c2vhdl.py [options] + +compile options: + + no_reuse : prevent register resuse + + no_concurrent : prevent concurrency + +tool options: + + iverilog : compiles using the iverilog compiler + + run : runs compiled code, used with iverilog option Index: chips2/documents/INTERCONNECT.rst =================================================================== --- chips2/documents/INTERCONNECT.rst (nonexistent) +++ chips2/documents/INTERCONNECT.rst (revision 2) @@ -0,0 +1,219 @@ +Interconnect Conventions +========================= + +These are the interface conventions followed by the VHDLToolbox. +The main aims of the interface are: + - To be simple to implement. + - Add little performance/logic overhead. + - Allow designs to grow without adding extra levels of asynchronous logic. + - Easy to interface with standard interconnects. + +:: + + RST >-o-----------------------------+ + CLK >-+-o-------------------------+ | + | | | | + | | +-----------+ | | +--------------+ + | | | TX | | | | RX | + | +---> | | +-----> | + +-----> | +-------> | + | | | | + | | | | + | out >=================> in | + | | _STB | | + | out >-----------------> in | + | | _ACK | | + | in <-----------------< out | + | | | | + +-----------+ +--------------+ + +Global Signals +-------------- + + +------+------------+-------------------+--------------+ + | Name | Direction | Type | Description | + +======+============+===================+==============+ + | CLK | input | std_logic Global | Clock | + +------+------------+-------------------+--------------+ + | RST | input | std_logic Global | Reset | + +------+------------+-------------------+--------------+ + +Interconnect Signals +-------------------- + + +----------------+------------+-------------------+------------------------------------------------------------+ + | Name | Direction | Type | Description | + +================+============+===================+============================================================+ + | | TX to RX | std_logic_vector | Payload Data | + +----------------+------------+-------------------+------------------------------------------------------------+ + | _STB | TX to RX | std_logic | '1' indicates that payload data is valid and TX is ready. | + +----------------+------------+-------------------+------------------------------------------------------------+ + | _ACK | TX to RX | std_logic | '1' indicates that RX is ready. | + +----------------+------------+-------------------+------------------------------------------------------------+ + +Interconnect Bus Transaction +---------------------------- + + - Both transmitter and receiver shall be synchronised to the '0' -> '1' transition of CLK. + - If RST is set to '1' upon the '0' -> '1' transition of clock the transmitter shall terminate any active bus transaction and set _STB to '0'. + - If RST is set to '1' upon the '0' -> '1' transition of clock the receiver shall terminate any active bus transaction and set _ACK to '0'. + - If RST is set to '0', normal operation shall commence as follows: + - The transmitter may insert wait states on the bus by setting _STB '0'. + - The transmitter shall set _STB to '1' to signify that data is valid. + - Once _STB has been set to '1', it shall remain at '1' until the transaction completes. + - The transmitter shall ensure that contains valid data for the entire period that _STB is '1'. + - The transmitter may set to any value when _STB is '0'. + - The receiver may insert wait states on the bus by setting _ACK to '0'. + - The receiver shall set _ACK to '1' to signify that it is ready to receive data. + - Once _ACK has been set to '1', it shall remain at '1' until the transaction completes. + - Whenever _STB is '1' and _ACK are '1', a bus transaction shall complete on the following '0' -> '1' transition of CLK. + +:: + +RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ------------------------------------------------ + X VALID X + ----- ------- ------------------------------------------------ + ------- +_STB | | + ----- ------------------------------------------------ + --- +_ACK | | + --------- ------------------------------------------------ + + + ^^^^ RX adds wait states + + ^^^^ Data transfers + +RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ------------------------------------------------ + X VALID X + ----- ------- ------------------------------------------------ + --- +_STB | | + --------- ------------------------------------------------ + ------- +_ACK | | + ----- ------------------------------------------------ + + + ^^^^ TX adds wait states + + ^^^^ Data transfers + +- Both the transmitter and receiver may commence a new transaction without inserting any wait states. + +:: +RST + -------------------------------------------------------------- + - - - - - - - - - - - - - - - + CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + - - - - - - - - - - - - - - - - + + ----- ------- ---- ---- -------------------------------------- + X D0 X D1 X D2 X + ----- ------- ---- ---- -------------------------------------- + ------------- +_STB | | + --------- -------------------------------------- + ----------------- +_ACK | | + ----- -------------------------------------- + + ^^^^ TX adds wait states + + ^^^^ Data transfers + + ^^^^ STB and ACK needn't return to 0 between data words + + +- The receiver may delay a transaction by inserting wait states until the transmitter indicates that data is available. + +- The transmitter shall not delay a transaction by inserting wait states until the receiver is ready to accept data. + +- Deadlock would occur if both the transmitter and receiver delayed a transaction until the other was ready. + +Example Transmitter FSM +----------------------- + +:: + + ... + + process + begin + wait until rising_edge(CLK); + + case STATE is + + ... + + when TRANSMIT_STATE => + + S_BUS_STB <= '1'; + if S_BUS_STB = '1' and BUS_ACK = '1'; + LOCAL_DATA <= BUS; + S_BUS_STB <= '0'; + STATE <= NEXT_STATE; + end if; + + ... + + if RST = '1' then + S_BUS_STB <= '0'; + ... + end if; + + end process; + + BUS_STB <= S_BUS_STB; + + ... + + +Example Reciever FSM +-------------------- + +:: + + ... + + process + begin + wait until rising_edge(CLK); + + case STATE is + + ... + + when RECIEVE_STATE => + + S_BUS_ACK <= '1'; + BUS <= LOCAL_DATA; + if BUS_STB = '1' and S_BUS_ACK = '1'; + S_BUS_ACK <= '0'; + STATE <= NEXT_STATE; + end if; + + ... + if RST = '1' then + S_BUS_ACK <= '0'; + ... + end if; + + end process; + + BUS_ACK <= S_BUS_ACK; + + ... Index: chips2/interconnect.py =================================================================== --- chips2/interconnect.py (nonexistent) +++ chips2/interconnect.py (revision 2) @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +from chips.api.api import * +import sys + + +my_chip = Chip("interconnect") +wire = Wire(my_chip) +Component("test_suite/producer.c")(my_chip, inputs={}, outputs={"z":wire}) +Component("test_suite/consumer.c")(my_chip, inputs={"a":wire}, outputs={}) +my_chip.generate_verilog() +my_chip.generate_testbench(100000) +my_chip.compile_iverilog(True) + +my_chip = Chip("interconnect") +wire = Wire(my_chip) +Component("test_suite/slow_producer.c")(my_chip, inputs={}, outputs={"z":wire}) +Component("test_suite/consumer.c")(my_chip, inputs={"a":wire}, outputs={}) +my_chip.generate_verilog() +my_chip.generate_testbench(100000) +my_chip.compile_iverilog(True) + +my_chip = Chip("interconnect") +wire = Wire(my_chip) +Component("test_suite/producer.c")(my_chip, inputs={}, outputs={"z":wire}) +Component("test_suite/slow_consumer.c")(my_chip, inputs={"a":wire}, outputs={}) +my_chip.generate_verilog() +my_chip.generate_testbench(100000) +my_chip.compile_iverilog(True) + +my_chip = Chip("interconnect") +wire = Wire(my_chip) +Component("test_suite/slow_producer.c")(my_chip, inputs={}, outputs={"z":wire}) +Component("test_suite/slow_consumer.c")(my_chip, inputs={"a":wire}, outputs={}) +my_chip.generate_verilog() +my_chip.generate_testbench(100000) +my_chip.compile_iverilog(True) + +os.remove("producer.v") +os.remove("consumer.v") +os.remove("interconnect_tb") +os.remove("interconnect.v") +os.remove("interconnect_tb.v")
chips2/interconnect.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/README.rst =================================================================== --- chips2/README.rst (nonexistent) +++ chips2/README.rst (revision 2) @@ -0,0 +1,32 @@ +Chips +===== + +Introduction +------------ + +Chips is a fast and simple way to design Logic Devices. You can think of +a Chips design as a network on a chip. Many C Programs are all executing in +parallel, streaming data between each other using fast on-chip connections. + +The interface is simple, design components using C, and connect them together +to form a chip using a simple python API. Behind the scenes, chips will comvert +C programs into efficient verilog implementation based on interconnected Finite +State Machines, or custom CPUs. + +Test +---- +$ cd test_suite +$ test_c2verilog + +Install +------- +$ sudo python setup install + +To Prepare a Source Distribution +-------------------------------- +$ python setup sdist +Distribution is contained in ./dist + +To Create a Windows Distribution +-------------------------------- +$ python setup bdist_wininst Index: chips2/chips/__init__.py =================================================================== Index: chips2/chips/api/api.py =================================================================== --- chips2/chips/api/api.py (nonexistent) +++ chips2/chips/api/api.py (revision 2) @@ -0,0 +1,271 @@ +from chips.compiler.exceptions import C2CHIPError +import chips.compiler.compiler +import os +import sys + +class Chip: + + """A Chip represents a collection of components connected together by + wires. As you create wires and component instances, you will need to tell + them which chip they belong to. Once you have a completed chip you can: + + + Implement it in verilog - using the generate_verilog method + + Automatically generate documentation - using the generate_document method + + You can create a new chip like this:: + + my_chip = Chip(name = "My Chip")""" + + + def __init__(self, name): + + """Takes a single argument *name*, the name of the chip""" + + self.name = name + self.instances = [] + self.wires = [] + self.inputs = [] + self.outputs = [] + self.components = [] + + def generate_verilog(self): + + """Generate verilog for the chip""" + + for i in self.wires: + if i.source is None: + raise C2CHIPError("wire %s has no source"%i.name) + if i.sink is None: + raise C2CHIPError("wire %s has no sink"%i.name) + + for i in self.inputs: + if i.sink is None: + raise C2CHIPError("input %s has no sink"%i.name) + + for i in self.outputs: + if i.source is None: + raise C2CHIPError("output %s has no source"%i.name) + + ports = ["clk", "rst"] + ports += ["%s"%i.name for i in self.inputs] + ports += ["%s_stb"%i.name for i in self.inputs] + ports += ["%s_ack"%i.name for i in self.inputs] + ports += ["%s"%i.name for i in self.outputs] + ports += ["%s_stb"%i.name for i in self.outputs] + ports += ["%s_ack"%i.name for i in self.outputs] + ports = ", ".join(ports) + + output_file = open(self.name + ".v", "w") + output_file.write("module %s(%s);\n"%(self.name, ports)) + output_file.write(" input clk;\n") + output_file.write(" input rst;\n") + for i in self.inputs: + output_file.write(" input [15:0] %s;\n"%i.name) + output_file.write(" input %s_stb;\n"%i.name) + output_file.write(" output %s_ack;\n"%i.name) + for i in self.outputs: + output_file.write(" output [15:0] %s;\n"%i.name) + output_file.write(" output %s_stb;\n"%i.name) + output_file.write(" input %s_ack;\n"%i.name) + for i in self.wires: + output_file.write(" wire [15:0] %s;\n"%i.name) + output_file.write(" wire %s_stb;\n"%i.name) + output_file.write(" wire %s_ack;\n"%i.name) + for instance in self.instances: + component = instance.component.name + output_file.write(" %s %s_%s(\n "%(component, component, id(instance))) + ports = [] + ports.append(".clk(clk)") + ports.append(".rst(rst)") + for name, i in instance.inputs.iteritems(): + ports.append(".input_%s(%s)"%(name, i.name)) + ports.append(".input_%s_stb(%s_stb)"%(name, i.name)) + ports.append(".input_%s_ack(%s_ack)"%(name, i.name)) + for name, i in instance.outputs.iteritems(): + ports.append(".output_%s(%s)"%(name, i.name)) + ports.append(".output_%s_stb(%s_stb)"%(name, i.name)) + ports.append(".output_%s_ack(%s_ack)"%(name, i.name)) + output_file.write(",\n ".join(ports)) + output_file.write(");\n") + output_file.write("endmodule\n") + output_file.close() + + def generate_testbench(self, stop_clocks=None): + + """Generate verilog for the test bench""" + + output_file = open(self.name + "_tb.v", "w") + output_file.write("module %s_tb;\n"%self.name) + output_file.write(" reg clk;\n") + output_file.write(" reg rst;\n") + for i in self.inputs: + output_file.write(" wire [15:0] %s;\n"%i.name) + output_file.write(" wire [15:0] %s_stb;\n"%i.name) + output_file.write(" wire [15:0] %s_ack;\n"%i.name) + for i in self.outputs: + output_file.write(" wire [15:0] %s;\n"%i.name) + output_file.write(" wire [15:0] %s_stb;\n"%i.name) + output_file.write(" wire [15:0] %s_ack;\n"%i.name) + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" rst <= 1'b1;\n") + output_file.write(" #50 rst <= 1'b0;\n") + output_file.write(" end\n\n") + + if stop_clocks: + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" #%s $finish;\n"%(10*stop_clocks)) + output_file.write(" end\n\n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" clk <= 1'b0;\n") + output_file.write(" while (1) begin\n") + output_file.write(" #5 clk <= ~clk;\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + output_file.write(" %s uut(\n "%(self.name)) + ports = [] + ports.append(".clk(clk)") + ports.append(".rst(rst)") + for i in self.inputs: + ports.append(".%s(%s)"%(i.name, i.name)) + ports.append(".%s_stb(%s_stb)"%(i.name, i.name)) + ports.append(".%s_ack(%s_ack)"%(i.name, i.name)) + for i in self.outputs: + ports.append(".%s(%s)"%(i.name, i.name)) + ports.append(".%s_stb(%s_stb)"%(i.name, i.name)) + ports.append(".%s_ack(%s_ack)"%(i.name, i.name)) + output_file.write(",\n ".join(ports)) + output_file.write(");\n") + output_file.write("endmodule\n") + output_file.close() + + def compile_iverilog(self, run=False): + + """Compile using the Iverilog simulator""" + + files = ["%s.v"%i.name for i in self.components] + files.append(self.name + ".v") + files.append(self.name + "_tb.v") + files = " ".join(files) + + os.system("iverilog -o %s %s"%(self.name + "_tb", files)) + if run: + return os.system("vvp %s"%(self.name + "_tb")) + + + +class Component: + + """You can use the component class to add new components to your chip. + Components are written in C, and you need to supply the C code for the + component when you create it. The Chips API will automatically compile the + C code, and extract the name, inputs, outputs and the documentation from the + code. + + If you want to keep the C file seperate you can read it in from a file like + this:: + + my_component = Adder(C_file="adder.c") + + Once you have defined a component you can use the __call__ method to create + an instance of the component. + + """ + + def __init__(self, C_file): + + """Takes a single string argument, the C code to compile""" + + self.name, self.inputs, self.outputs, self.doc = chips.compiler.compiler.comp(C_file) + + def __call__(self, chip, inputs, outputs): + + """Takes three arguments: + + chip, the chip that the component instance belongs to. + + inputs, a list of *Wires* (or *Inputs*) to connect to the component inputs + + outputs, a list of *Wires* (or *Outputs*) to connect to the component outputs""" + return _Instance(self, chip, inputs, outputs) + + +class _Instance: + + """This class represents a component instance. You don't normaly need to + create them directly, use the Component.__call__ method.""" + + def __init__(self, component, chip, inputs, outputs): + self.chip = chip + self.inputs = inputs + self.outputs = outputs + self.component = component + self.chip.instances.append(self) + if component not in chip.components: + chip.components.append(component) + + if len(self.component.inputs) != len(self.inputs): + raise C2CHIPError("Instance %s does not have the right number or inputs"%self.name) + + if len(self.component.outputs) != len(self.outputs): + raise C2CHIPError("Instance %s does not have the right number or outputs"%self.name) + + for i in inputs.values(): + if i.sink is not None: + raise C2CHIPError("%s allready has a sink"%i.name) + i.sink = self + + for i in outputs.values(): + if i.source is not None: + raise C2CHIPError("%s has allready has a source"%i.name) + i.source = self + + for i in inputs.keys(): + if i not in self.component.inputs: + raise C2CHIPError("%s is not an input of component %s"%(i, component.name)) + + for i in outputs.keys(): + if i not in self.component.outputs: + raise C2CHIPError("%s has allready has a source %s"%(i, component.name)) + +class Wire: + + """Create a connection between two components. A wire is a point to point + connection with one input and one output""" + + def __init__(self, chip): + self.chip = chip + chip.wires.append(self) + self.source = None + self.sink = None + self.name = "wire_" + str(id(self)) + +class Input: + + """Create an input to the chip.""" + + def __init__(self, chip, name): + + """Takes a single argument, the chip to which the input belongs, and a + string representing the name""" + + self.chip = chip + chip.inputs.append(self) + self.sink = None + self.name = name + +class Output: + + """Create an output from the chip.""" + + def __init__(self, chip, name): + + """Takes two argument, the chip to which the output belongs, and a + string representing the name""" + + self.chip = chip + chip.outputs.append(self) + self.source = None + self.name = name Index: chips2/chips/api/__init__.py =================================================================== Index: chips2/chips/compiler/parse_tree.py =================================================================== --- chips2/chips/compiler/parse_tree.py (nonexistent) +++ chips2/chips/compiler/parse_tree.py (revision 2) @@ -0,0 +1,672 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +class NotConstant(Exception): + pass + +def value(expression): + + """If an expression can be evaluated at compile time, return the value""" + + if hasattr(expression, "value"): + return truncate(expression.value()) + else: + raise NotConstant + +def constant_fold(expression): + + """Replace an expression with a constant if possible""" + + try: + return Constant(value(expression)) + except NotConstant: + return expression + +def truncate(number): + + """Truncate arithmetic results to the target number of bits""" + + #sign = number & 0x10000 + #number = number & 0xffff + #if sign: + #number = ~0xffff | number + return int(number) + +class Process: + def generate(self): + instructions = [] + for function in self.functions: + if hasattr(function, "declarations"): + instructions.extend(function.generate()) + instructions.append({"op" :"jmp_and_link", + "dest" :self.main.return_address, + "label":"function_%s"%id(self.main)}) + instructions.append({"op":"stop"}) + for function in self.functions: + if not hasattr(function, "declarations"): + instructions.extend(function.generate()) + return instructions + +class Function: + def generate(self): + instructions = [] + instructions.append({"op":"label", "label":"function_%s"%id(self)}) + instructions.extend(self.statement.generate()) + if not hasattr(self, "return_value"): + instructions.append({"op":"jmp_to_reg", "src":self.return_address}) + return instructions + +class Break: + def generate(self): return [{"op":"goto", "label":"break_%s"%id(self.loop)}] + +class Continue: + def generate(self): return [{"op":"goto", "label":"continue_%s"%id(self.loop)}] + +class Assert: + def generate(self): + result = self.allocator.new(self.expression.size) + instructions = self.expression.generate(result) + self.allocator.free(result) + instructions.append({"op":"assert", "src":result, "line":self.line, "file":self.filename}) + return instructions + +class Return: + def generate(self): + if hasattr(self, "expression"): + instructions = self.expression.generate(self.function.return_value) + else: + instructions = [] + instructions.append({"op":"jmp_to_reg", "src":self.function.return_address}) + return instructions + +class Report: + def generate(self): + result = self.allocator.new(self.expression.size) + instructions = self.expression.generate(result) + self.allocator.free(result) + instructions.append({"op":"report", + "src":result, + "line":self.line, + "file":self.filename, + "signed":self.expression.signed}) + return instructions + +class WaitClocks: + def generate(self): + result = self.allocator.new(self.expression.size) + instructions = self.expression.generate(result) + self.allocator.free(result) + instructions.append({"op":"wait_clocks", "src":result}) + return instructions + +class If: + def generate(self): + try: + if value(self.expression): + return self.true_statement.generate() + else: + if self.false_statement: + return self.false_statement.generate() + else: + return [] + except NotConstant: + result = self.allocator.new(self.expression.size) + instructions = [] + instructions.extend(self.expression.generate(result)) + instructions.append({"op" :"jmp_if_false", + "src" :result, + "label":"else_%s"%id(self)}) + self.allocator.free(result) + instructions.extend(self.true_statement.generate()) + instructions.append({"op":"goto", "label":"end_%s"%id(self)}) + instructions.append({"op":"label", "label":"else_%s"%id(self)}) + if self.false_statement: + instructions.extend(self.false_statement.generate()) + instructions.append({"op":"label", "label":"end_%s"%id(self)}) + return instructions + +class Switch: + def generate(self): + result = self.allocator.new(self.expression.size) + test = self.allocator.new(self.expression.size) + instructions = self.expression.generate(result) + for value, case in self.cases.iteritems(): + instructions.append({"op":"==", "dest":test, "src":result, "right":value, "signed":True}) + instructions.append({"op":"jmp_if_true", "src":test, "label":"case_%s"%id(case)}) + if hasattr(self, "default"): + instructions.append({"op":"goto", "label":"case_%s"%id(self.default)}) + self.allocator.free(result) + self.allocator.free(test) + instructions.extend(self.statement.generate()) + instructions.append({"op":"label", "label":"break_%s"%id(self)}) + return instructions + +class Case: + def generate(self): + return [{"op":"label", "label":"case_%s"%id(self)}] + +class Default: + def generate(self): + return [{"op":"label", "label":"case_%s"%id(self)}] + +class Loop: + def generate(self): + instructions = [{"op":"label", "label":"begin_%s"%id(self)}] + instructions.append({"op":"label", "label":"continue_%s"%id(self)}) + instructions.extend(self.statement.generate()) + instructions.append({"op":"goto", "label":"begin_%s"%id(self)}) + instructions.append({"op":"label", "label":"break_%s"%id(self)}) + return instructions + +class For: + def generate(self): + instructions = [] + if hasattr(self, "statement1"): + instructions.extend(self.statement1.generate()) + instructions.append({"op":"label", "label":"begin_%s"%id(self)}) + if hasattr(self, "expression"): + result = self.allocator.new(self.expression.size) + instructions.extend(self.expression.generate(result)) + instructions.append({"op":"jmp_if_false", "src":result, "label":"end_%s"%id(self)}) + self.allocator.free(result) + instructions.extend(self.statement3.generate()) + instructions.append({"op":"label", "label":"continue_%s"%id(self)}) + if hasattr(self, "statement2"): + instructions.extend(self.statement2.generate()) + instructions.append({"op":"goto", "label":"begin_%s"%id(self)}) + instructions.append({"op":"label", "label":"end_%s"%id(self)}) + instructions.append({"op":"label", "label":"break_%s"%id(self)}) + return instructions + +class Block: + def generate(self): + instructions = [] + for statement in self.statements: + instructions.extend(statement.generate()) + return instructions + +class CompoundDeclaration: + def __init__(self, declarations): + self.declarations = declarations + + def generate(self): + instructions = [] + for declaration in self.declarations: + instructions.extend(declaration.generate()); + return instructions + +class VariableDeclaration: + def __init__(self, allocator, initializer, name, type_, size, signed): + self.initializer = initializer + self.allocator = allocator + self.type_ = type_ + self.size = size + self.signed = signed + self.name = name + def instance(self): + register = self.allocator.new(self.size, "variable "+self.name) + return VariableInstance(register, self.initializer, self.type_, self.size, self.signed) + +class VariableInstance: + def __init__(self, register, initializer, type_, size, signed): + self.register = register + self.type_ = type_ + self.initializer = initializer + self.size = size + self.signed = signed + def generate(self): + return self.initializer.generate(self.register) + +class ArrayDeclaration: + def __init__(self, + allocator, + size, + type_, + element_type, + element_size, + element_signed, + initializer = None, + initialize_memory = False): + + self.allocator = allocator + self.type_ = type_ + self.size = size + self.signed = False + self.element_type = element_type + self.element_size = element_size + self.element_signed = element_signed + self.initializer = initializer + self.initialize_memory = initialize_memory + + def instance(self): + location = self.allocator.new_array(self.size, self.initializer, self.element_size) + register = self.allocator.new(2, "array") + return ArrayInstance(location, + register, + self.size, + self.type_, + self.initializer, + self.initialize_memory, + self.element_type, + self.element_size, + self.element_signed) + +class ArrayInstance: + def __init__(self, + location, + register, + size, + type_, + initializer, + initialize_memory, + element_type, + element_size, + element_signed): + + self.register = register + self.location = location + self.type_ = type_ + self.size = size + self.signed = False + self.element_type = element_type + self.element_size = element_size + self.element_signed = element_signed + self.initializer = initializer + self.initialize_memory = initialize_memory + + def generate(self, result=None): + instructions = [] + #If initialize memory is true, the memory content will initialised (as at configuration time) + #If initialize memory is false, then the memory will need to be filled by the program. + if not self.initialize_memory and self.initializer is not None: + location = 0 + for value in self.initializer: + instructions.append({ + "op":"memory_write_literal", + "address":location, + "value":value, + "element_size":self.element_size + }) + location += 1 + instructions.append({ + "op":"literal", + "literal":self.location, + "dest":self.register + }) + #this bit here is to make string literals work, + #in this case an array instance is created implicitly, + #but the value of the expression is the array register. + if result is not None and result != self.register: + instructions.append({ + "op" :"move", + "dest":result, + "src" :self.register + }) + return instructions + +class StructDeclaration: + def __init__(self, members): + self.members = members + + def instance(self): + instances = {} + for name, declaration in self.members.iteritems(): + instances[name] = declaration.instance() + return StructInstance(instances) + +class StructInstance: + def __init__(self, members): + self.members = members + self.type_ = "struct" + + def generate(self): + instructions = [] + for member in self.members.values(): + instructions.extend(member.generate()) + return instructions + +class Argument: + def __init__(self, + name, + type_, + size, + signed, + parser, + element_type, + element_size, + element_signed): + self.type_=type_ + self.size=size + self.signed=signed + self.element_type = element_type + self.element_size = element_size + self.element_signed = element_signed + parser.scope[name] = self + self.register = parser.allocator.new(size, "function argument "+name) + def generate(self): return [] + +class DiscardExpression: + def __init__(self, expression, allocator): + self.expression = expression + self.allocator = allocator + + def generate(self): + result = self.allocator.new(self.expression.size) + instructions = self.expression.generate(result) + self.allocator.free(result) + return instructions + +#...then Expressions... + +#Expressions generate methods accept a result argument. +#This indicates which register to put the result in. + +#Expressions may also provide a value method which returns the value of an xpression +#if it can be calculated at compile time. + +def AND(left, right): + return ANDOR(left, right, "jmp_if_false") + +def OR(left, right): + return ANDOR(left, right, "jmp_if_true") + +class ANDOR: + def __init__(self, left, right, op): + self.left = constant_fold(left) + self.right = constant_fold(right) + self.op = op + self.type_ = "int" + self.size = left.size + self.signed = left.signed + + def generate(self, result): + instructions = self.left.generate(result) + instructions.append({"op":self.op, "src":result, "label":"end_%s"%id(self)}) + instructions.extend(self.right.generate(result)) + instructions.append({"op":"label", "label":"end_%s"%id(self)}) + return instructions + + def value(self): + if self.op == "jmp_if_false": + return value(self.left) and value(self.right) + else: + return value(self.left) or value(self.right) + +class Binary: + def __init__(self, operator, left, right, allocator): + self.left = constant_fold(left) + self.right = constant_fold(right) + self.operator = operator + self.allocator = allocator + self.type_ = self.left.type_ + self.size = max(left.size, right.size) + self.signed = left.signed and right.signed + + def generate(self, result): + new_register = self.allocator.new(self.size) + try: + instructions = self.right.generate(new_register) + instructions.append({"op" :self.operator, + "dest":result, + "left":value(self.left), + "src":new_register, + "signed":self.signed}) + except NotConstant: + try: + instructions = self.left.generate(new_register) + instructions.append({"op" :self.operator, + "dest" :result, + "src" :new_register, + "right":value(self.right), + "signed" :self.signed}) + except NotConstant: + instructions = self.left.generate(new_register) + right = self.allocator.new(self.right.size) + instructions.extend(self.right.generate(right)) + instructions.append({"op" :self.operator, + "dest":result, + "src" :new_register, + "srcb":right, + "signed":self.signed}) + self.allocator.free(right) + self.allocator.free(new_register) + return instructions + + def value(self): + return eval("%s %s %s"%(value(self.left), self.operator, value(self.right))) + +def SizeOf(expression): + return Constant(expression.size) + +class Unary: + def __init__(self, operator, expression, allocator): + self.expression = constant_fold(expression) + self.operator = operator + self.type_ = self.expression.type_ + self.size = expression.size + self.signed = expression.signed + self.allocator = allocator + + def generate(self, result): + new_register = self.allocator.new(self.size) + instructions = self.expression.generate(new_register) + instructions.extend([{"op":self.operator, "dest":result, "src":new_register}]) + self.allocator.free(new_register) + return instructions + + def value(self): + return eval("%s%s"%(self.operator, value(self.expression))) + +class FunctionCall: + def generate(self, result): + instructions = [] + for expression, argument in zip(self.arguments, self.function.arguments): + instructions.extend(expression.generate(argument.register)) + instructions.append({"op" :"jmp_and_link", + "dest" :self.function.return_address, + "label":"function_%s"%id(self.function)}) + if hasattr(self.function, "return_value"): + instructions.append({"op" :"move", + "dest" :result, + "src" :self.function.return_value}) + return instructions + +class Output: + def __init__(self, name, expression): + self.name = name + self.expression = expression + self.type_ = "int" + self.size = expression.size + + def generate(self, result): + instructions = self.expression.generate(result); + instructions.append({"op" :"write", "src" :result, "output":self.name}) + return instructions + +class FileWrite: + def __init__(self, name, expression): + self.name = name + self.expression = expression + self.type_ = "int" + self.size = expression.size + + def generate(self, result): + instructions = self.expression.generate(result); + instructions.append({"op" :"file_write", "src" :result, "file_name":self.name}) + return instructions + +class Input: + def __init__(self, name): + self.name = name + self.type_ = "int" + self.size = 2 + self.signed = True + + def generate(self, result): + return [{"op" :"read", "dest" :result, "input":self.name}] + +class FileRead: + def __init__(self, name): + self.name = name + self.type_ = "int" + self.size = 2 + self.signed = True + + def generate(self, result): + return [{"op" :"file_read", "dest" :result, "file_name":self.name}] + +class Ready: + def __init__(self, name): + self.name = name + self.type_ = "int" + self.size = 2 + self.signed = True + + def generate(self, result): + return [{"op" :"ready", "dest" :result, "input":self.name}] + +class Array: + def __init__(self, declaration, allocator): + self.declaration = declaration + self.allocator = allocator + self.storage = "register" + self.type_ = self.declaration.type_ + self.size = int(self.declaration.size) * 2 + self.signed = False + + def generate(self, result): + instructions = [] + if result != self.declaration.register: + instructions.append({"op" :"move", + "dest":result, + "src" :self.declaration.register}) + return instructions + +class ArrayIndex: + def __init__(self, declaration, index_expression, allocator): + self.declaration = declaration + self.allocator = allocator + self.index_expression = index_expression + self.storage = "memory" + self.type_ = self.declaration.element_type + self.size = self.declaration.element_size + self.signed = self.declaration.element_signed + + def generate(self, result): + instructions = [] + offset = self.allocator.new(2) + address = self.allocator.new(2) + instructions.extend(self.index_expression.generate(offset)) + instructions.append({"op" :"+", + "dest" :address, + "src" :offset, + "srcb" :self.declaration.register, + "signed":False}) + instructions.append({"op" :"memory_read_request", + "src" :address, + "sequence": id(self), + "element_size":self.size}) + instructions.append({"op" :"memory_read_wait", + "src" :address, + "sequence": id(self), + "element_size":self.size}) + instructions.append({"op" :"memory_read", + "src" :address, + "dest" :result, + "sequence": id(self), + "element_size":self.size}) + self.allocator.free(address) + self.allocator.free(offset) + return instructions + +class Variable: + def __init__(self, declaration, allocator): + self.declaration = declaration + self.allocator = allocator + self.storage = "register" + self.type_ = self.declaration.type_ + self.size = self.declaration.size + self.signed = self.declaration.signed + + def generate(self, result): + instructions = [] + if result != self.declaration.register: + instructions.append({"op" :"move", + "dest":result, + "src" :self.declaration.register}) + return instructions + +class PostIncrement: + def __init__(self, operator, lvalue, allocator): + self.operator = operator + self.lvalue = lvalue + self.allocator = allocator + self.type_ = self.lvalue.declaration.type_ + self.size = self.lvalue.declaration.size + self.signed = self.lvalue.declaration.signed + + def generate(self, result): + + instructions = [] + + instructions.append({"op" :"move", + "src" :self.lvalue.declaration.register, + "dest" :result}) + + instructions.append({"op" :self.operator, + "dest" :self.lvalue.declaration.register, + "right" :1, + "src" :self.lvalue.declaration.register, + "signed":self.signed}) + + return instructions + +class Assignment: + def __init__(self, lvalue, expression, allocator): + self.lvalue = lvalue + self.expression = expression + self.allocator = allocator + self.type_ = self.lvalue.type_ + self.size = self.lvalue.size + self.signed = self.lvalue.signed + + def generate(self, result): + instructions = self.expression.generate(result) + if self.lvalue.storage == "register": + if result != self.lvalue.declaration.register: + instructions.append({"op" : "move", + "dest" : self.lvalue.declaration.register, + "src" : result}) + + elif self.lvalue.storage == "memory": + index = self.allocator.new(2) + address = self.allocator.new(2) + instructions.extend(self.lvalue.index_expression.generate(index)) + instructions.append({"op" :"+", + "dest" :address, + "src" :index, + "srcb" :self.lvalue.declaration.register, + "signed" :self.signed}) + instructions.append({"op" :"memory_write", + "src" :address, + "srcb" :result, + "element_size" :self.lvalue.declaration.element_size}) + self.allocator.free(index) + self.allocator.free(address) + + return instructions + +class Constant: + def __init__(self, value, size=2, signed=True): + self._value = value + self.type_ = "int" + self.size = size + self.signed = signed + + def generate(self, result): + instructions = [{"op":"literal", "dest":result, "literal":self._value}] + return instructions + + def value(self): + return self._value Index: chips2/chips/compiler/builtins.py =================================================================== --- chips2/chips/compiler/builtins.py (nonexistent) +++ chips2/chips/compiler/builtins.py (revision 2) @@ -0,0 +1,120 @@ +#!/usr/bin/env python +"""Support Library for builtin Functionality""" + +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2013, Jonathan P Dawson" +__version__ = "0.1" + +builtins=""" + +unsigned unsigned_modulo_yyyy; +unsigned unsigned_divide_xxxx(unsigned dividend, unsigned divisor){ + unsigned remainder = 0; + unsigned quotient = 0; + unsigned i = 0; + + while(1){ + if( dividend & (1 << 15) ){ + remainder |= 1; + } + if( remainder >= divisor ){ + quotient |= 1; + remainder -= divisor; + } + if(i==15) break; + i++; + quotient <<= 1; + remainder <<= 1; + dividend <<= 1; + } + + unsigned_modulo_yyyy = remainder; + return quotient; +} + +unsigned unsigned_modulo_xxxx(unsigned dividend, unsigned divisor){ + unsigned_divide_xxxx(dividend, divisor); + return unsigned_modulo_yyyy; +} + +int divide_xxxx(int dividend, int divisor){ + unsigned udividend, udivisor, uquotient; + unsigned dividend_sign, divisor_sign, quotient_sign; + dividend_sign = dividend & 0x8000u; + divisor_sign = divisor & 0x8000u; + quotient_sign = dividend_sign ^ divisor_sign; + udividend = dividend_sign ? -dividend : dividend; + udivisor = divisor_sign ? -divisor : divisor; + uquotient = unsigned_divide_xxxx(udividend, udivisor); + return quotient_sign ? -uquotient : uquotient; +} + +int modulo_xxxx(int dividend, int divisor){ + unsigned udividend, udivisor, uquotient; + unsigned dividend_sign, divisor_sign; + int modulo; + dividend_sign = dividend & 0x8000u; + divisor_sign = divisor & 0x8000u; + udividend = dividend_sign ? -dividend : dividend; + udivisor = divisor_sign ? -divisor : divisor; + modulo = unsigned_modulo_xxxx(udividend, udivisor); + modulo = dividend_sign ? -modulo : modulo; + return modulo; +} + +long unsigned long_unsigned_modulo_yyyy; +long unsigned long_unsigned_divide_xxxx(long unsigned dividend, long unsigned divisor){ + long unsigned remainder = 0; + long unsigned quotient = 0; + unsigned i = 0; + + while(1){ + if( dividend & (1 << 31) ){ + remainder |= 1; + } + if( remainder >= divisor ){ + quotient |= 1; + remainder -= divisor; + } + if(i==31) break; + i++; + quotient <<= 1; + remainder <<= 1; + dividend <<= 1; + } + long_unsigned_modulo_yyyy = remainder; + return quotient; +} + +long int long_divide_xxxx(long int dividend, long int divisor){ + long unsigned udividend, udivisor, uquotient; + long unsigned dividend_sign, divisor_sign, quotient_sign; + dividend_sign = dividend & 0x80000000ul; + divisor_sign = divisor & 0x80000000ul; + quotient_sign = dividend_sign ^ divisor_sign; + udividend = dividend_sign ? -dividend : dividend; + udivisor = divisor_sign ? -divisor : divisor; + uquotient = long_unsigned_divide_xxxx(udividend, udivisor); + return quotient_sign ? -uquotient : uquotient; +} + + +long unsigned long_unsigned_modulo_xxxx(long unsigned dividend, long unsigned divisor){ + long_unsigned_divide_xxxx(dividend, divisor); + return long_unsigned_modulo_yyyy; +} + +long int long_modulo_xxxx(long int dividend, long int divisor){ + long unsigned udividend, udivisor; + long unsigned dividend_sign, divisor_sign, quotient_sign; + long int modulo; + dividend_sign = dividend & 0x80000000ul; + divisor_sign = divisor & 0x80000000ul; + udividend = dividend_sign ? -dividend : dividend; + udivisor = divisor_sign ? -divisor : divisor; + modulo = long_unsigned_modulo_xxxx(udividend, udivisor); + modulo = dividend_sign ? -modulo : modulo; + return modulo; +} + +"""
chips2/chips/compiler/builtins.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/chips/compiler/compiler.py =================================================================== --- chips2/chips/compiler/compiler.py (nonexistent) +++ chips2/chips/compiler/compiler.py (revision 2) @@ -0,0 +1,84 @@ +#!/usr/bin/env python +"""A C to Verilog compiler""" + +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2013, Jonathan P Dawson" +__version__ = "0.1" + +import sys +import os + +from chips.compiler.parser import Parser +from chips.compiler.exceptions import C2CHIPError +from chips.compiler.optimizer import parallelise +from chips.compiler.optimizer import cleanup_functions +from chips.compiler.optimizer import cleanup_registers +from chips.compiler.tokens import Tokens +from chips.compiler.verilog_speed import generate_CHIP as generate_CHIP_speed +from chips.compiler.verilog_area import generate_CHIP as generate_CHIP_area + +def comp(input_file, options=[]): + + reuse = "no_reuse" not in options + initialize_memory = "no_initialize_memory" not in options + + try: + if "speed" not in options: + + #Optimize for area + parser = Parser(input_file, reuse, initialize_memory) + process = parser.parse_process() + name = process.main.name + instructions = process.generate() + instructions = cleanup_functions(instructions) + instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers) + output_file = name + ".v" + output_file = open(output_file, "w") + inputs, outputs = generate_CHIP_area( + input_file, + name, + instructions, + output_file, + registers, + parser.allocator.memory_size_2, + parser.allocator.memory_size_4, + initialize_memory, + parser.allocator.memory_content_2, + parser.allocator.memory_content_4) + output_file.close() + + else: + + #Optimize for speed + parser = Parser(input_file, reuse, initialize_memory) + process = parser.parse_process() + name = process.main.name + instructions = process.generate() + instructions = cleanup_functions(instructions) + instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers) + if "no_concurrent" in sys.argv: + frames = [[i] for i in instructions] + else: + frames = parallelise(instructions) + output_file = name + ".v" + output_file = open(output_file, "w") + inputs, outputs = generate_CHIP_speed( + input_file, + name, + frames, + output_file, + registers, + parser.allocator.memory_size_2, + parser.allocator.memory_size_4, + initialize_memory, + parser.allocator.memory_content_2, + parser.allocator.memory_content_4) + output_file.close() + + except C2CHIPError as err: + print "Error in file:", err.filename, "at line:", err.lineno + print err.message + sys.exit(-1) + + + return name, inputs, outputs, "" Index: chips2/chips/compiler/parser.py =================================================================== --- chips2/chips/compiler/parser.py (nonexistent) +++ chips2/chips/compiler/parser.py (revision 2) @@ -0,0 +1,820 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +from parse_tree import * +from tokens import Tokens +from allocator import Allocator + +class Parser: + + """Turn the C input file into a tree of expressions and statements.""" + + def __init__(self, input_file, reuse, initialize_memory): + self.scope = {} + self.function = None + self.loop = None + self.tokens = Tokens(input_file) + self.allocator = Allocator(reuse) + self.structs = [] + self.initialize_memory = initialize_memory + + def parse_process(self): + process = Process() + process.allocator = self.allocator + process.inputs = [] + process.outputs = [] + process.functions = [] + while not self.tokens.end(): + if self.tokens.peek() == "struct": + self.parse_define_struct() + elif self.tokens.peek() == "typedef": + self.parse_typedef_struct() + else: + process.functions.append(self.parse_function()) + process.main = self.main + return process + + def parse_type_specifier(self): + type_specifiers = [] + + while self.tokens.peek() in ["signed", "unsigned", "short", "long", "char", "int", "void"] + self.structs: + type_specifiers.append(self.tokens.get()) + + signed = True + if "unsigned" in type_specifiers: + signed = False + if "signed" in type_specifiers: + self.tokens.error("Cannot be signed and unsigned") + + size = 2 + if "long" in type_specifiers: + if "short" in type_specifiers: + self.tokens.error("Cannot be long and short") + size = 4 + + type_ = "int" + for i in type_specifiers: + if i in self.structs: + type_ = i + size = 2 + signed = False + + if "void" in type_specifiers: + type_ = "void" + size = 2 + signed = False + + + return type_, size, signed + + def parse_function(self): + function = Function() + function.allocator = self.allocator + stored_scope = self.scope + type_, size, signed = self.parse_type_specifier() + name = self.tokens.get() + + #check if it is a global declaration + if self.tokens.peek() != "(": + return self.parse_global_declaration(type_, size, signed, name) + + #otherwise continue parsing a function + self.tokens.expect("(") + function.name = name + function.type_ = type_ + function.size = size + function.signed = signed + function.return_address = self.allocator.new(2, function.name+" return address") + if type_ != "void": + function.return_value = self.allocator.new(function.size, function.name+" return value") + function.arguments = [] + while self.tokens.peek() != ")": + argument_type, argument_size, argument_signed = self.parse_type_specifier() + if argument_type in ["void"]: + self.tokens.error("argument cannot be void") + argument = self.tokens.get() + element_type = None + element_size = None + element_signed = None + if self.tokens.peek() == "[": + self.tokens.expect("[") + self.tokens.expect("]") + element_type = argument_type + element_size = argument_size + element_signed = argument_signed + argument_type+="[]" + argument_size = 2 + argument_signed = False + + function.arguments.append(Argument( + argument, + argument_type, + argument_size, + argument_signed, + self, + element_type, + element_size, + element_signed)) + if self.tokens.peek() == ",": + self.tokens.expect(",") + else: + break + self.tokens.expect(")") + self.function = function + function.statement = self.parse_statement() + if type_ != "void" and not hasattr(function, "return_statement"): + self.tokens.error("Function must have a return statement") + self.function = None + self.scope = stored_scope + self.scope[function.name] = function + #main thread is last function + self.main = function + return function + + def parse_break(self): + break_ = Break() + break_.loop = self.loop + self.tokens.expect("break") + self.tokens.expect(";") + return break_ + + def parse_continue(self): + continue_ = Continue() + continue_.loop = self.loop + self.tokens.expect("continue") + self.tokens.expect(";") + return continue_ + + def parse_return(self): + return_ = Return() + return_.function = self.function + self.function.return_statement = return_ + self.tokens.expect("return") + if hasattr(self.function, "return_value"): + return_.expression = self.parse_expression() + self.tokens.expect(";") + return return_ + + def parse_assert(self): + assert_ = Assert() + assert_.allocator = self.allocator + self.tokens.expect("assert") + self.tokens.expect("(") + assert_.expression = self.parse_expression() + self.tokens.expect(")") + self.tokens.expect(";") + assert_.line = self.tokens.lineno + assert_.filename = self.tokens.filename + return assert_ + + def parse_report(self): + report_ = Report() + report_.allocator = self.allocator + self.tokens.expect("report") + self.tokens.expect("(") + report_.expression = self.parse_expression() + self.tokens.expect(")") + self.tokens.expect(";") + report_.line = self.tokens.lineno + report_.filename = self.tokens.filename + return report_ + + def parse_wait_clocks(self): + wait_clocks = WaitClocks() + wait_clocks.allocator = self.allocator + self.tokens.expect("wait_clocks") + self.tokens.expect("(") + wait_clocks.expression = self.parse_expression() + self.tokens.expect(")") + self.tokens.expect(";") + wait_clocks.line = self.tokens.lineno + return wait_clocks + + def parse_statement(self): + if self.tokens.peek() in ["unsigned", "int", "short", "long", "char"] + self.structs: + return self.parse_compound_declaration() + elif self.tokens.peek() == "struct": + return self.parse_struct_declaration() + elif self.tokens.peek() == "if": + return self.parse_if() + elif self.tokens.peek() == "while": + return self.parse_while() + elif self.tokens.peek() == "for": + return self.parse_for() + elif self.tokens.peek() == "return": + return self.parse_return() + elif self.tokens.peek() == "break": + return self.parse_break() + elif self.tokens.peek() == "continue": + return self.parse_continue() + elif self.tokens.peek() == "{": + return self.parse_block() + elif self.tokens.peek() == "assert": + return self.parse_assert() + elif self.tokens.peek() == "report": + return self.parse_report() + elif self.tokens.peek() == "switch": + return self.parse_switch() + elif self.tokens.peek() == "case": + return self.parse_case() + elif self.tokens.peek() == "default": + return self.parse_default() + elif self.tokens.peek() == "wait_clocks": + return self.parse_wait_clocks() + else: + expression = self.parse_discard() + self.tokens.expect(";") + return expression + + def parse_discard(self): + return DiscardExpression(self.parse_expression(), self.allocator) + + def parse_assignment(self): + assignment_operators = [ + "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=" + ] + lvalue = self.parse_ternary_expression() + if self.tokens.peek() in assignment_operators: + if not hasattr(lvalue, "declaration"): + self.tokens.error( + "left hand operand of assignment is not modifiable" + ) + operator = self.tokens.get() + if operator == "=": + expression = self.parse_ternary_expression() + else: + expression = Binary( + operator[:-1], + lvalue, + self.parse_ternary_expression(), + self.allocator + ) + if not compatible(lvalue.type_, expression.type_): + self.tokens.error( + "type mismatch in assignment" + ) + return Assignment(lvalue, expression, self.allocator) + else: + return lvalue + + def parse_if(self): + if_ = If() + if_.allocator = self.allocator + self.tokens.expect("if") + self.tokens.expect("(") + if_.expression = self.parse_expression() + if if_.expression.type_ not in ["unsigned", "int", "short", "long", "char"]: + self.tokens.error( + "if statement conditional must be an integer like expression" + ) + self.tokens.expect(")") + if_.true_statement = self.parse_statement() + if self.tokens.peek() == "else": + self.tokens.expect("else") + if_.false_statement = self.parse_statement() + else: + if_.false_statement = None + return if_ + + def parse_switch(self): + switch = Switch() + switch.cases = {} + self.tokens.expect("switch") + self.tokens.expect("(") + expression = self.parse_expression() + if expression.type_ not in ["unsigned", "int", "short", "long", "char"]: + self.tokens.error( + "switch statement expression must be an integer like expression" + ) + self.tokens.expect(")") + stored_loop = self.loop + self.loop = switch + statement = self.parse_statement() + self.loop = stored_loop + switch.expression = expression + switch.allocator = self.allocator + switch.statement = statement + return switch + + def parse_case(self): + self.tokens.expect("case") + expression = self.parse_expression() + if expression.type_ not in ["int"]: + self.tokens.error( + "case expression must be an integer like expression" + ) + self.tokens.expect(":") + try: + expression = value(expression) + case = Case() + self.loop.cases[expression] = case + except NotConstant: + self.tokens.error("case expression must be constant") + except AttributeError: + self.tokens.error( + "case statements may only be use inside a switch statment" + ) + return case + + def parse_default(self): + self.tokens.expect("default") + self.tokens.expect(":") + default = Default() + if not hasattr(self.loop, "cases"): + self.tokens.error( + "default statements may only be used inside a switch statment" + ) + if hasattr(self.loop, "default"): + self.tokens.error( + "A switch statement may only have one default statement" + ) + self.loop.default=default + return default + + def parse_while(self): + loop = Loop() + self.tokens.expect("while") + self.tokens.expect("(") + expression = self.parse_expression() + self.tokens.expect(")") + stored_loop = self.loop + self.loop = loop + statement = self.parse_statement() + self.loop = stored_loop + + if_ = If() + loop.statement = if_ + break_ = Break() + break_.loop = loop + if_.allocator = self.allocator + if expression.type_ not in ["int"]: + self.tokens.error( + "if statement conditional must be an integer like expression" + ) + if_.expression = expression + if_.false_statement = break_ + if_.true_statement = statement + + return loop + + def parse_for(self): + for_ = For() + for_.allocator = self.allocator + self.tokens.expect("for") + self.tokens.expect("(") + if self.tokens.peek() != ";": + for_.statement1 = self.parse_discard() + self.tokens.expect(";") + if self.tokens.peek() != ";": + for_.expression = self.parse_expression() + if for_.expression.type_ not in ["unsigned", "int", "short", "long", "char"]: + self.tokens.error( + "for statement conditional must be an integer like expression" + ) + self.tokens.expect(";") + if self.tokens.peek() != ")": + for_.statement2 = self.parse_discard() + self.tokens.expect(")") + stored_loop = self.loop + self.loop = for_ + for_.statement3 = self.parse_statement() + self.loop = stored_loop + return for_ + + def parse_block(self): + block = Block() + stored_scope = self.scope + self.tokens.expect("{") + block.statements = [] + while self.tokens.peek() != "}": + block.statements.append(self.parse_statement()) + self.tokens.expect("}") + self.scope = stored_scope + return block + + def parse_struct_body(self): + self.tokens.expect("{") + members = {} + while self.tokens.peek() != "}": + type_, size, signed = self.parse_type_specifier() + name = self.tokens.get() + members[name] = self.parse_declaration(type_, size, signed, name) + self.tokens.expect(";") + self.tokens.expect("}") + return members + + def parse_typedef_struct(self): + self.tokens.expect("typedef") + self.tokens.expect("struct") + declaration = StructDeclaration(self.parse_struct_body()) + name = self.tokens.get() + self.tokens.expect(";") + self.scope[name] = declaration + self.structs.append(name) + + def parse_define_struct(self): + self.tokens.expect("struct") + name = self.tokens.get() + declaration = StructDeclaration(self.parse_struct_body()) + self.tokens.expect(";") + self.scope[name] = declaration + + def parse_struct_declaration(self): + self.tokens.expect("struct") + struct_name = self.tokens.get() + name = self.tokens.get() + self.tokens.expect(";") + instance = self.scope[struct_name].instance() + self.scope[name] = instance + return instance + + def parse_global_declaration(self, type_, size, signed, name): + instances = [] + while True: + instance = self.parse_declaration(type_, size, signed, name).instance() + self.scope[name] = instance + instances.append(instance) + if self.tokens.peek() == ",": + self.tokens.expect(",") + else: + break + name = self.tokens.get() + self.tokens.expect(";") + return CompoundDeclaration(instances) + + def parse_compound_declaration(self): + type_, size, signed = self.parse_type_specifier() + instances = [] + while True: + name = self.tokens.get() + instance = self.parse_declaration(type_, size, signed, name).instance() + self.scope[name] = instance + instances.append(instance) + if self.tokens.peek() == ",": + self.tokens.expect(",") + else: + break + name = None + self.tokens.expect(";") + return CompoundDeclaration(instances) + + def parse_declaration(self, type_, size, signed, name): + #struct declaration + if type_ in self.structs: + declaration = self.scope[type_] + elif type_ in ["int"]: + #array declaration + if self.tokens.peek() == "[": + array_size = None + self.tokens.expect("[") + if self.tokens.peek() != "]": + array_size = int(self.tokens.get()) + self.tokens.expect("]") + initializer = None + if self.tokens.peek() == "=": + self.tokens.expect("=") + initializer = self.tokens.get() + initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0] + array_size = len(initializer) + if array_size is None: + self.tokens.error("array size must be specified if not initialized") + array_type=type_+"[]" + initialize_memory = self.initialize_memory + declaration = ArrayDeclaration(self.allocator, + array_size, + array_type, + type_, + size, + signed, + initializer, + self.initialize_memory) + + #simple variable declaration + else: + if self.tokens.peek() == "=": + self.tokens.expect("=") + initializer = self.parse_ternary_expression() + else: + initializer = Constant(0) + declaration = VariableDeclaration( + self.allocator, + initializer, + name, + type_, + size, + signed + ) + + return declaration + + def parse_expression(self): + expression = self.parse_assignment() + return expression + + def parse_ternary_expression(self): + expression = constant_fold(self.parse_or_expression()) + while self.tokens.peek() in ["?"]: + self.tokens.expect("?") + true_expression = constant_fold(self.parse_or_expression()) + self.tokens.expect(":") + false_expression = constant_fold(self.parse_or_expression()) + expression = OR(AND(expression, true_expression), false_expression) + return expression + + def parse_or_expression(self): + expression = self.parse_and_expression() + while self.tokens.peek() in ["||"]: + self.tokens.expect("||") + expression = OR(expression, self.parse_and_expression()) + return expression + + def parse_and_expression(self): + expression = self.parse_binary_expression(["|"]) + while self.tokens.peek() in ["&&"]: + self.tokens.expect("&&") + expression = AND(expression, self.parse_binary_expression(["|"])) + return expression + + def substitute_function(self, operator, left, right): + #Some things can't be implemented in verilog, substitute them with a function + if operator in ["/", "%"]: + function_call = FunctionCall() + function_call.arguments = [left, right] + if operator == "/": + if left.signed and right.signed: + if max(left.size, right.size) == 4: + function_call.function = self.scope["long_divide_xxxx"] + else: + function_call.function = self.scope["divide_xxxx"] + else: + if max(left.size, right.size) == 4: + function_call.function = self.scope["long_unsigned_divide_xxxx"] + else: + function_call.function = self.scope["unsigned_divide_xxxx"] + elif operator == "%": + if left.signed and right.signed: + if max(left.size, right.size) == 4: + function_call.function = self.scope["long_modulo_xxxx"] + else: + function_call.function = self.scope["modulo_xxxx"] + else: + if max(left.size, right.size) == 4: + function_call.function = self.scope["long_unsigned_modulo_xxxx"] + else: + function_call.function = self.scope["unsigned_modulo_xxxx"] + function_call.type_ = function_call.function.type_ + function_call.size = function_call.function.size + function_call.signed = function_call.function.signed + return function_call + else: + return Binary( + operator, + left, + right, + self.allocator + ) + + def parse_binary_expression(self, operators): + operator_precedence = { + "|": ["^"], + "^": ["&"], + "&": ["==", "!="], + "==": ["<", ">", "<=", ">="], + "<": ["<<", ">>"], + "<<": ["+", "-"], + "+": ["*", "/", "%"], + } + if operators[0] not in operator_precedence: + expression = self.parse_unary_expression() + while self.tokens.peek() in operators: + operator = self.tokens.get() + right = self.parse_unary_expression() + expression = self.substitute_function(operator, expression, right) + return expression + else: + next_operators = operator_precedence[operators[0]] + expression = self.parse_binary_expression(next_operators) + while self.tokens.peek() in operators: + expression = Binary( + self.tokens.get(), + expression, + self.parse_binary_expression(next_operators), + self.allocator + ) + return expression + + def parse_unary_expression(self): + if self.tokens.peek() == "!": + operator = self.tokens.get() + expression = self.parse_postfix_expression() + return Binary("==", expression, Constant(0), self.allocator) + elif self.tokens.peek() == "-": + operator = self.tokens.get() + expression = self.parse_postfix_expression() + return Binary("-", Constant(0), expression, self.allocator) + elif self.tokens.peek() == "~": + operator = self.tokens.get() + expression = self.parse_postfix_expression() + return Unary("~", expression, self.allocator) + elif self.tokens.peek() == "sizeof": + operator = self.tokens.get() + expression = self.parse_unary_expression() + return SizeOf(expression) + else: + return self.parse_postfix_expression() + + def parse_postfix_expression(self): + expression = self.parse_paren_expression() + while self.tokens.peek() in ["++", "--"]: + operator = self.tokens.get() + expression = PostIncrement( + operator[:-1], + expression, + self.allocator + ) + return expression + + def parse_paren_expression(self): + if self.tokens.peek() == "(": + self.tokens.expect("(") + expression = self.parse_expression() + self.tokens.expect(")") + else: + expression = self.parse_number_or_variable() + return expression + + def parse_number_or_variable(self): + if self.tokens.peek()[0].isalpha(): + name = self.tokens.get() + if self.tokens.peek() == "(": + return self.parse_function_call(name) + else: + return self.parse_variable(name) + else: + return self.parse_number() + + def parse_file_read(self): + self.tokens.expect("(") + file_name = self.tokens.get() + file_name = file_name.strip('"').decode("string_escape") + self.tokens.expect(")") + return FileRead(file_name) + + def parse_file_write(self): + self.tokens.expect("(") + expression = self.parse_expression() + self.tokens.expect(",") + file_name = self.tokens.get() + file_name = file_name.strip('"').decode("string_escape") + self.tokens.expect(")") + return FileWrite(file_name, expression) + + def parse_input(self, name): + input_name = name.replace("input_", "") + self.tokens.expect("(") + self.tokens.expect(")") + return Input(input_name) + + def parse_ready(self, name): + input_name = name.replace("ready_", "") + self.tokens.expect("(") + self.tokens.expect(")") + return Ready(input_name) + + def parse_output(self, name): + output_name = name.replace("output_", "") + self.tokens.expect("(") + expression = self.parse_expression() + self.tokens.expect(")") + return Output(output_name, expression) + + def parse_function_call(self, name): + if name.startswith("input_"): + return self.parse_input(name) + if name.startswith("ready_"): + return self.parse_ready(name) + if name.startswith("output_"): + return self.parse_output(name) + if name == "file_read": + return self.parse_file_read() + if name == "file_write": + return self.parse_file_write() + function_call = FunctionCall() + function_call.arguments = [] + self.tokens.expect("(") + while self.tokens.peek() != ")": + function_call.arguments.append(self.parse_expression()) + if self.tokens.peek() == ",": + self.tokens.expect(",") + else: + break + self.tokens.expect(")") + + if name not in self.scope: + self.tokens.error("Unknown function: %s"%name) + + function_call.function = self.scope[name] + function_call.type_ = function_call.function.type_ + function_call.size = function_call.function.size + function_call.signed = function_call.function.signed + required_arguments = len(function_call.function.arguments) + actual_arguments = len(function_call.arguments) + if required_arguments != actual_arguments: + self.tokens.error("Function %s takes %s arguments %s given."%( + name, + len(function_call.function.arguments), + len(function_call.arguments) + )) + required_arguments = function_call.function.arguments + actual_arguments = function_call.arguments + for required, actual in zip(required_arguments, actual_arguments): + if not compatible(required.type_, actual.type_): + self.tokens.error("Type mismatch expected type : %s got: %s."%( + required.type_, + actual.type_ + )) + + + return function_call + + def parse_number(self): + token = self.tokens.get() + size = 2 + signed = True + if token.startswith("'"): + try: + token = eval(token) + value = ord(token) + except SyntaxError: + self.tokens.error("%s is not a character literal"%token) + elif token.startswith('"'): + try: + initializer = [ord(i) for i in token.strip('"').decode("string_escape")] + [0] + size = len(initializer) + initialize_memory = self.initialize_memory + declaration = ArrayDeclaration( + self.allocator, + size, + "int[]", + "int", + 2, + False, + initializer, + self.initialize_memory) + return declaration.instance() + except SyntaxError: + self.tokens.error("%s is not a character literal"%token) + else: + try: + if "U" in token.upper(): + signed = False + if "L" in token.upper(): + size = 4 + token = token.upper().replace("U", "") + value = int(eval(token)) + + if signed: + if value > 2**((size * 8)-1) - 1: + self.tokens.error("value too large") + if value < -(2**((size * 8)-1)): + self.tokens.error("value too small") + else: + if value > 2**(size * 8) - 1: + self.tokens.error("value too large") + if value < 0: + self.tokens.error("value too small") + + except SyntaxError: + self.tokens.error("%s is not an integer literal"%token) + return Constant(value, size, signed) + + def parse_variable(self, name): + if name not in self.scope: + self.tokens.error("Unknown variable: %s"%name) + instance = self.scope[name] + return self.parse_variable_array_struct(instance) + + def parse_variable_array_struct(self, instance): + if instance.type_ in ["unsigned", "int", "short", "long", "char"]: + return Variable(instance, self.allocator) + elif instance.type_.endswith("[]"): + if self.tokens.peek() == "[": + self.tokens.expect("[") + index_expression = self.parse_expression() + self.tokens.expect("]") + if index_expression.type_ not in ["unsigned", "int", "short", "long", "char"]: + self.tokens.error( + "array indices must be an integer like expression" + ) + return ArrayIndex(instance, index_expression, self.allocator) + else: + return Array(instance, self.allocator) + elif instance.type_ == "struct": + self.tokens.expect(".") + member = self.tokens.get() + instance = instance.members[member] + return self.parse_variable_array_struct(instance) + +def compatible(left, right): + return left == right Index: chips2/chips/compiler/__init__.py =================================================================== Index: chips2/chips/compiler/verilog_area.py =================================================================== --- chips2/chips/compiler/verilog_area.py (nonexistent) +++ chips2/chips/compiler/verilog_area.py (revision 2) @@ -0,0 +1,799 @@ +#!/usr/bin/env python +"""Generate Verilog Implementation of Instructions + +The area optimized implementation uses a CPU like architecture. ++ Instructions are implemented in block RAM. ++ Registers are implemented in dual port RAM. ++ Only one instruction can be executed at a time. ++ The CPU uses a pipeline architecture, and will take 2 clocks to execute a taken branch. ++ A minimal instruction set is determined at compile time, and only those instructions are implemented. + +""" + +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2013, Jonathan P Dawson" +__version__ = "0.1" + +def unique(l): + + """In the absence of set in older python implementations, make list values unique""" + + return dict(zip(l, l)).keys() + +def log2(instructions): + + """Integer only algorithm to calculate the number of bits needed to store a number""" + + bits = 1 + power = 2 + while power < instructions: + bits += 1 + power *= 2 + return bits + +def print_verilog_literal(size, value): + + """Print a verilog literal with expicilt size""" + + if(value >= 0): + return "%s'd%s"%(size, value) + else: + return "-%s'd%s"%(size, abs(value)) + +def remove_register_hazards(instructions): + + """search through instructions, and remove register hazards""" + + wait_2_for = None + wait_1_for = None + new_instructions = [] + for instruction in instructions: + wait = 0 + if "src" in instruction: + if instruction["src"] == wait_1_for: + wait = max(wait, 1) + if instruction["src"] == wait_2_for: + wait = max(wait, 2) + if "srcb" in instruction: + if instruction["srcb"] == wait_1_for: + wait = max(wait, 1) + if instruction["srcb"] == wait_2_for: + wait = max(wait, 2) + for i in range(wait): + new_instructions.append({"op":"nop"}) + new_instructions.append(instruction) + + if instruction["op"] != "label": + wait_1_for = wait_2_for + if "dest" in instruction: + wait_2_for = instruction["dest"] + else: + wait_2_for = None + return new_instructions + +def generate_instruction_set(instructions): + + """Calculate the required instruction set""" + + instruction_set = [] + instruction_memory = [] + for instruction in instructions: + opcode = {} + encoded_instruction = {} + encoded_instruction["dest"] = 0 + encoded_instruction["src"] = 0 + encoded_instruction["srcb"] = 0 + encoded_instruction["literal"] = 0 + opcode["op"] = instruction["op"] + opcode["right"] = False + opcode["unsigned"] = False + opcode["literal"] = False + + if "signed" in instruction: + opcode["unsigned"] = not instruction["signed"] + + if "element_size" in instruction: + opcode["element_size"] = instruction["element_size"] + + if "file" in instruction: + opcode["file_"] = instruction["file"] + + if "line" in instruction: + opcode["line"] = instruction["line"] + + if "input" in instruction: + opcode["input"] = instruction["input"] + + if "output" in instruction: + opcode["output"] = instruction["output"] + + if "dest" in instruction: + encoded_instruction["dest"] = instruction["dest"] + + if "src" in instruction: + encoded_instruction["src"] = instruction["src"] + + if "srcb" in instruction: + encoded_instruction["srcb"] = instruction["srcb"] + + if "left" in instruction: + opcode["literal"] = True + encoded_instruction["literal"] = instruction["left"] + + if "right" in instruction: + opcode["literal"] = True + opcode["right"] = True + encoded_instruction["literal"] = instruction["right"] + + if "literal" in instruction: + opcode["literal"] = True + encoded_instruction["literal"] = instruction["literal"] + + if "label" in instruction: + opcode["literal"] = True + encoded_instruction["literal"] = instruction["label"] + + if opcode not in instruction_set: + instruction_set.append(opcode) + + for op, test_opcode in enumerate(instruction_set): + if test_opcode == opcode: + encoded_instruction["op"] = op + encoded_instruction["comment"] = repr(instruction) + instruction_memory.append(encoded_instruction) + break + + return instruction_set, instruction_memory + +def calculate_jumps(instructions): + + """change symbolic labels into numeric addresses""" + + #calculate the values of jump locations + location = 0 + labels = {} + new_instructions = [] + for instruction in instructions: + if instruction["op"] == "label": + labels[instruction["label"]] = location + else: + new_instructions.append(instruction) + location += 1 + instructions = new_instructions + + #substitue real values for labeled jump locations + for instruction in instructions: + if "label" in instruction: + instruction["label"]=labels[instruction["label"]] + + return instructions + +def generate_declarations(instructions, no_tb_mode, register_bits, opcode_bits): + + """Generate verilog declarations""" + + #list all inputs and outputs used in the program + inputs = unique([i["input"] for i in instructions if "input" in i]) + outputs = unique([i["output"] for i in instructions if "output" in i]) + input_files = unique([i["file_name"] for i in instructions if "file_read" == i["op"]]) + output_files = unique([i["file_name"] for i in instructions if "file_write" == i["op"]]) + testbench = not inputs and not outputs and not no_tb_mode + + #Do not generate a port in testbench mode + inports = [ + ("input_" + i, 16) for i in inputs + ] + [ + ("input_" + i + "_stb", 1) for i in inputs + ] + [ + ("output_" + i + "_ack", 1) for i in outputs + ] + + outports = [ + ("output_" + i, 16) for i in outputs + ] + [ + ("output_" + i + "_stb", 1) for i in outputs + ] + [ + ("input_" + i + "_ack", 1) for i in inputs + ] + + #create list of signals + signals = [ + ("timer", 16), + ("timer_enable", 1), + ("stage_0_enable", 1), + ("stage_1_enable", 1), + ("stage_2_enable", 1), + ("program_counter", log2(len(instructions))), + ("program_counter_0", log2(len(instructions))), + ("instruction_0", 32 + register_bits*2 + opcode_bits), + ("opcode_0", opcode_bits), + ("dest_0", register_bits), + ("src_0", register_bits), + ("srcb_0", register_bits), + ("literal_0", 32), + ("program_counter_1", log2(len(instructions))), + ("opcode_1", opcode_bits), + ("dest_1", register_bits), + ("register_1", 32), + ("registerb_1", 32), + ("literal_1", 32), + ("dest_2", register_bits), + ("result_2", 32), + ("write_enable_2", 1), + ("address_2", 16), + ("data_out_2", 16), + ("data_in_2", 16), + ("memory_enable_2", 1), + ("address_4", 16), + ("data_out_4", 32), + ("data_in_4", 32), + ("memory_enable_4", 1), + ] + [ + ("s_output_" + i + "_stb", 16) for i in outputs + ] + [ + ("s_output_" + i, 16) for i in outputs + ] + [ + ("s_input_" + i + "_ack", 16) for i in inputs + ] + + if testbench: + signals.append(("clk", 1)) + signals.append(("rst", 1)) + else: + inports.append(("clk", 1)) + inports.append(("rst", 1)) + + return inputs, outputs, input_files, output_files, testbench, inports, outports, signals + +def generate_CHIP(input_file, + name, + instructions, + output_file, + registers, + memory_size_2, + memory_size_4, + initialize_memory, + memory_content_2, + memory_content_4, + no_tb_mode=False): + + """A big ugly function to crunch through all the instructions and generate the CHIP equivilent""" + + instructions = remove_register_hazards(instructions) + instructions = calculate_jumps(instructions) + instruction_set, instruction_memory = generate_instruction_set(instructions) + register_bits = log2(len(registers)); + opcode_bits = log2(len(instruction_set)); + instruction_bits = 32 + register_bits*2 + opcode_bits + declarations = generate_declarations(instructions, no_tb_mode, register_bits, opcode_bits) + inputs, outputs, input_files, output_files, testbench, inports, outports, signals = declarations + + #output the code in verilog + output_file.write("//name : %s\n"%name) + output_file.write("//tag : c components\n") + for i in inputs: + output_file.write("//input : input_%s:16\n"%i) + for i in outputs: + output_file.write("//output : output_%s:16\n"%i) + output_file.write("//source_file : %s\n"%input_file) + output_file.write("///%s\n"%"".join(["=" for i in name])) + output_file.write("///\n") + output_file.write("///*Created by C2CHIP*\n\n") + + + output_file.write("//////////////////////////////////////////////////////////////////////////////\n") + output_file.write("// Register Allocation\n") + output_file.write("// ===================\n") + output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20))) + for register, definition in registers.iteritems(): + register_name, size = definition + output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20))) + + output_file.write(" \n`timescale 1ns/1ps\n") + output_file.write("module %s"%name) + + all_ports = [name for name, size in inports + outports] + if all_ports: + output_file.write("(") + output_file.write(",".join(all_ports)) + output_file.write(");\n") + else: + output_file.write(";\n") + + output_file.write(" integer file_count;\n") + + input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)])) + for i in input_files.values(): + output_file.write(" integer %s;\n"%i) + + output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)])) + for i in output_files.values(): + output_file.write(" integer %s;\n"%i) + + + def write_declaration(object_type, name, size, value=None): + if size == 1: + output_file.write(object_type) + output_file.write(name) + if value is not None: + output_file.write("= %s'd%s"%(size,value)) + output_file.write(";\n") + else: + output_file.write(object_type) + output_file.write("[%i:0]"%(size-1)) + output_file.write(" ") + output_file.write(name) + if value is not None: + output_file.write("= %s'd%s"%(size,value)) + output_file.write(";\n") + + for name, size in inports: + write_declaration(" input ", name, size) + + for name, size in outports: + write_declaration(" output ", name, size) + + for name, size in signals: + write_declaration(" reg ", name, size) + + memory_size_2 = int(memory_size_2) + memory_size_4 = int(memory_size_4) + if memory_size_2: + output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1)) + if memory_size_4: + output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1)) + + output_file.write(" reg [%s:0] instructions [%i:0];\n"%(instruction_bits-1, len(instructions)-1)) + output_file.write(" reg [31:0] registers [%i:0];\n"%(len(registers)-1)) + + + #generate clock and reset in testbench mode + if testbench: + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // CLOCK AND RESET GENERATION \n") + output_file.write(" // \n") + output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n") + output_file.write(" // output file can be executed directly within a verilog simulator. \n") + output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n") + output_file.write(" // the output file. \n") + output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n") + output_file.write(" // or for instantiation within a larger design.\n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" rst <= 1'b1;\n") + output_file.write(" #50 rst <= 1'b0;\n") + output_file.write(" end\n\n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" clk <= 1'b0;\n") + output_file.write(" while (1) begin\n") + output_file.write(" #5 clk <= ~clk;\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + #Generate a state machine to execute the instructions + binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=", + "<=", "==", "!="] + + + if initialize_memory and (memory_content_2 or memory_content_4): + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // MEMORY INITIALIZATION \n") + output_file.write(" // \n") + output_file.write(" // In order to reduce program size, array contents have been stored into \n") + output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n") + output_file.write(" // initialized when the FPGA configures. \n") + output_file.write(" // Memory will not be re-initialized at reset. \n") + output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + for location, content in memory_content_2.iteritems(): + output_file.write(" memory_2[%s] = %s;\n"%(location, content)) + for location, content in memory_content_4.iteritems(): + output_file.write(" memory_4[%s] = %s;\n"%(location, content)) + output_file.write(" end\n\n") + + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // INSTRUCTION INITIALIZATION \n") + output_file.write(" // \n") + output_file.write(" // Initialise the contents of the instruction memory \n") + output_file.write(" //\n") + output_file.write(" // Intruction Set\n") + output_file.write(" // ==============\n") + for num, opcode in enumerate(instruction_set): + output_file.write(" // %s %s\n"%(num, opcode)) + + output_file.write(" // Intructions\n") + output_file.write(" // ===========\n") + output_file.write(" \n initial\n") + output_file.write(" begin\n") + for location, instruction in enumerate(instruction_memory): + output_file.write(" instructions[%s] = {%s, %s, %s, %s};//%s\n"%( + location, + print_verilog_literal(opcode_bits, instruction["op"]), + print_verilog_literal(register_bits, instruction["dest"]), + print_verilog_literal(register_bits, instruction["src"]), + print_verilog_literal(32, instruction["srcb"] | instruction["literal"]), + instruction["comment"])) + output_file.write(" end\n\n") + + if input_files or output_files: + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // OPEN FILES \n") + output_file.write(" // \n") + output_file.write(" // Open all files used at the start of the process \n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + for file_name, file_ in input_files.iteritems(): + output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name)) + for file_name, file_ in output_files.iteritems(): + output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name)) + output_file.write(" end\n\n") + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // CPU IMPLEMENTAION OF C PROCESS \n") + output_file.write(" // \n") + output_file.write(" // This section of the file contains a CPU implementing the C process. \n") + + output_file.write(" \n always @(posedge clk)\n") + output_file.write(" begin\n\n") + + if memory_size_2: + output_file.write(" //implement memory for 2 byte x n arrays\n") + output_file.write(" if (memory_enable_2 == 1'b1) begin\n") + output_file.write(" memory_2[address_2] <= data_in_2;\n") + output_file.write(" end\n") + output_file.write(" data_out_2 <= memory_2[address_2];\n") + output_file.write(" memory_enable_2 <= 1'b0;\n\n") + + if memory_size_4: + output_file.write(" //implement memory for 4 byte x n arrays\n") + output_file.write(" if (memory_enable_4 == 1'b1) begin\n") + output_file.write(" memory_4[address_4] <= data_in_4;\n") + output_file.write(" end\n") + output_file.write(" data_out_4 <= memory_4[address_4];\n") + output_file.write(" memory_enable_4 <= 1'b0;\n\n") + + output_file.write(" write_enable_2 <= 0;\n") + + output_file.write(" //stage 0 instruction fetch\n") + output_file.write(" if (stage_0_enable) begin\n") + output_file.write(" stage_1_enable <= 1;\n") + output_file.write(" instruction_0 <= instructions[program_counter];\n") + output_file.write(" opcode_0 = instruction_0[%s:%s];\n"%( + register_bits * 2 + opcode_bits + 31, + register_bits * 2 + 32)) + output_file.write(" dest_0 = instruction_0[%s:%s];\n"%( + register_bits * 2 + 31, + register_bits + 32)) + output_file.write(" src_0 = instruction_0[%s:32];\n"%( + register_bits + 31)) + output_file.write(" srcb_0 = instruction_0[%s:0];\n"%(register_bits-1)) + output_file.write(" literal_0 = instruction_0[31:0];\n") + output_file.write(" if(write_enable_2) begin\n") + output_file.write(" registers[dest_2] <= result_2;\n") + output_file.write(" end\n") + output_file.write(" program_counter_0 <= program_counter;\n") + output_file.write(" program_counter <= program_counter + 1;\n") + output_file.write(" end\n\n") + + output_file.write(" //stage 1 opcode fetch\n") + output_file.write(" if (stage_1_enable) begin\n") + output_file.write(" stage_2_enable <= 1;\n") + output_file.write(" register_1 <= registers[src_0];\n") + output_file.write(" registerb_1 <= registers[srcb_0];\n") + output_file.write(" dest_1 <= dest_0;\n") + output_file.write(" literal_1 <= literal_0;\n") + output_file.write(" opcode_1 <= opcode_0;\n") + output_file.write(" program_counter_1 <= program_counter_0;\n") + output_file.write(" end\n\n") + + output_file.write(" //stage 2 opcode fetch\n") + output_file.write(" if (stage_2_enable) begin\n") + output_file.write(" dest_2 <= dest_1;\n") + output_file.write(" case(opcode_1)\n\n") + + #A frame is executed in each state + for opcode, instruction in enumerate(instruction_set): + + if instruction["op"] == "literal": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= literal_1;\n") + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "move": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= register_1;\n") + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "~": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= ~register_1;\n") + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] in binary_operators: + if instruction["literal"]: + if instruction["unsigned"]: + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + if instruction["right"]: + output_file.write(" result_2 <= $unsigned(register_1) %s $unsigned(literal_1);\n"%(instruction["op"])) + else: + output_file.write(" result_2 <= $unsigned(literal_1) %s $unsigned(register_1);\n"%(instruction["op"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + else: + if instruction["op"] == ">>": + instruction["op"] = ">>>" + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + if instruction["right"]: + output_file.write(" result_2 <= $signed(register_1) %s $signed(literal_1);\n"%(instruction["op"])) + else: + output_file.write(" result_2 <= $signed(literal_1) %s $signed(register_1);\n"%(instruction["op"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + else: + if instruction["unsigned"]: + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= $unsigned(register_1) %s $unsigned(registerb_1);\n"%(instruction["op"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + else: + if instruction["op"] == ">>": + instruction["op"] = ">>>" + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= $signed(register_1) %s $signed(registerb_1);\n"%(instruction["op"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "jmp_if_false": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" if (register_1 == 0) begin\n"); + output_file.write(" program_counter <= literal_1;\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "jmp_if_true": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" if (register_1 != 0) begin\n"); + output_file.write(" program_counter <= literal_1;\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "jmp_and_link": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" program_counter <= literal_1;\n") + output_file.write(" result_2 <= program_counter_1 + 1;\n") + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "jmp_to_reg": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" program_counter <= register_1;\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "goto": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" program_counter <= literal_1;\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "file_read": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", result_2);\n"%( + input_files[instruction["file_"]])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "file_write": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" $fdisplay(%s, \"%%d\", register_1);\n"%( + output_files[instruction["file_name"]])) + output_file.write(" end\n\n") + + elif instruction["op"] == "read": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" stage_0_enable <= 0;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"]) + output_file.write(" end\n\n") + + elif instruction["op"] == "ready": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= 0;\n") + output_file.write(" result_2[0] <= input_%s_stb;\n"%( + instruction["input"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "write": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" stage_0_enable <= 0;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"]) + output_file.write(" s_output_%s <= register_1;\n"%instruction["output"]) + output_file.write(" end\n\n") + + elif instruction["op"] == "memory_read_request": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" address_%s <= register_1;\n"%( + instruction["element_size"])) + output_file.write(" end\n\n") + + elif instruction["op"] == "memory_read_wait": + pass + + elif instruction["op"] == "memory_read": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" result_2 <= data_out_%s;\n"%( + instruction["element_size"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "memory_write": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" address_%s <= register_1;\n"%( + instruction["element_size"])) + output_file.write(" data_in_%s <= registerb_1;\n"%( + instruction["element_size"])) + output_file.write(" memory_enable_%s <= 1'b1;\n"%( + instruction["element_size"])) + output_file.write(" end\n\n") + + elif instruction["op"] == "assert": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" if (register_1 == 0) begin\n") + output_file.write(" $display(\"Assertion failed at line: %s in file: %s\");\n"%( + instruction["line"], + instruction["file_"])) + output_file.write(" $finish_and_return(1);\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "wait_clocks": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + output_file.write(" timer <= register_1;\n") + output_file.write(" timer_enable <= 1;\n") + output_file.write(" stage_0_enable <= 0;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "report": + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + if instruction["unsigned"]: + output_file.write(' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_1));\n'%( + instruction["line"], + instruction["file_"])) + else: + output_file.write(' $display ("%%d (report at line: %s in file: %s)", $signed(register_1));\n'%( + instruction["line"], + instruction["file_"],)) + output_file.write(" end\n\n") + + elif instruction["op"] == "stop": + #If we are in testbench mode stop the simulation + #If we are part of a larger design, other C programs may still be running + output_file.write(" 16'd%s:\n"%(opcode)) + output_file.write(" begin\n") + for file_ in input_files.values(): + output_file.write(" $fclose(%s);\n"%file_) + for file_ in output_files.values(): + output_file.write(" $fclose(%s);\n"%file_) + if testbench: + output_file.write(' $finish;\n') + output_file.write(" stage_0_enable <= 0;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" end\n\n") + + + output_file.write(" endcase\n") + output_file.write(" end\n") + + for instruction in instruction_set: + + if instruction["op"] == "read": + output_file.write(" if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%( + instruction["input"], + instruction["input"])) + output_file.write(" result_2 <= input_%s;\n"%(instruction["input"])) + output_file.write(" write_enable_2 <= 1;\n") + output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"]) + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 1;\n") + output_file.write(" stage_2_enable <= 1;\n") + output_file.write(" end\n\n") + + elif instruction["op"] == "write": + output_file.write(" if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%( + instruction["output"], + instruction["output"])) + output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"]) + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 1;\n") + output_file.write(" stage_2_enable <= 1;\n") + output_file.write(" end\n\n") + + output_file.write(" if (timer == 0) begin\n") + output_file.write(" if (timer_enable) begin\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 1;\n") + output_file.write(" stage_2_enable <= 1;\n") + output_file.write(" timer_enable <= 0;\n") + output_file.write(" end\n") + output_file.write(" end else begin\n") + output_file.write(" timer <= timer - 1;\n") + output_file.write(" end\n\n") + + #Reset program counter and control signals + output_file.write(" if (rst == 1'b1) begin\n") + output_file.write(" stage_0_enable <= 1;\n") + output_file.write(" stage_1_enable <= 0;\n") + output_file.write(" stage_2_enable <= 0;\n") + output_file.write(" timer <= 0;\n") + output_file.write(" timer_enable <= 0;\n") + output_file.write(" program_counter <= 0;\n") + for i in inputs: + output_file.write(" s_input_%s_ack <= 0;\n"%(i)) + for i in outputs: + output_file.write(" s_output_%s_stb <= 0;\n"%(i)) + output_file.write(" end\n") + output_file.write(" end\n") + for i in inputs: + output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i)) + for i in outputs: + output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i)) + output_file.write(" assign output_%s = s_output_%s;\n"%(i, i)) + output_file.write("\nendmodule\n") + + return inputs, outputs
chips2/chips/compiler/verilog_area.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/chips/compiler/allocator.py =================================================================== --- chips2/chips/compiler/allocator.py (nonexistent) +++ chips2/chips/compiler/allocator.py (revision 2) @@ -0,0 +1,47 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +class Allocator: + + """Maintain a pool of registers, variables and arrays. Keep track of what they are used for.""" + + def __init__(self, reuse): + self.registers = [] + self.all_registers = {} + self.memory_size_2 = 0 + self.memory_size_4 = 0 + self.reuse = reuse + self.memory_content_2 = {} + self.memory_content_4 = {} + + def new_array(self, size, contents, element_size): + if element_size == 2: + reg = self.memory_size_2 + self.memory_size_2 += int(size) + if contents is not None: + for location, value in enumerate(contents, reg): + self.memory_content_2[location] = value + return reg + elif element_size == 4: + reg = self.memory_size_4 + self.memory_size_4 += int(size) + if contents is not None: + for location, value in enumerate(contents, reg): + self.memory_content_4[location] = value + return reg + + + + def new(self, size, name="temporary_register"): + assert type(size) == int + reg = 0 + while reg in self.registers: + reg += 1 + self.registers.append(reg) + self.all_registers[reg] = (name, size) + return reg + + def free(self, register): + if register in self.registers and self.reuse: + self.registers.remove(register) Index: chips2/chips/compiler/exceptions.py =================================================================== --- chips2/chips/compiler/exceptions.py (nonexistent) +++ chips2/chips/compiler/exceptions.py (revision 2) @@ -0,0 +1,14 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +import os + +class C2CHIPError(Exception): + def __init__(self, message, filename=None, lineno=None): + self.message = message + if filename is not None: + self.filename = os.path.abspath(filename) + else: + self.filename = None + self.lineno = lineno Index: chips2/chips/compiler/optimizer.py =================================================================== --- chips2/chips/compiler/optimizer.py (nonexistent) +++ chips2/chips/compiler/optimizer.py (revision 2) @@ -0,0 +1,199 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +def cleanup_functions(instructions): + + """Remove functions that are not called""" + + + #This is an iterative processr. Once a function is removed, + #there may be more unused functions + while 1: + + #find function calls + live_functions = {} + for instruction in instructions: + if instruction["op"] == "jmp_and_link": + if instruction["label"].startswith("function"): + live_functions[instruction["label"]] = None + + #remove instructions without function calls + kept_instructions = [] + generate_on = True + for instruction in instructions: + if instruction["op"] == "label": + if instruction["label"].startswith("function"): + if instruction["label"] in live_functions: + generate_on = True + else: + generate_on = False + if generate_on: + kept_instructions.append(instruction) + + if len(instructions) == len(kept_instructions): + return kept_instructions + instructions = kept_instructions + +def reallocate_registers(instructions, registers): + + register_map = {} + new_registers = {} + n = 0 + for register, definition in registers.iteritems(): + register_map[register] = n + new_registers[n] = definition + n+=1 + + for instruction in instructions: + if "dest" in instruction: + instruction["dest"] = register_map[instruction["dest"]] + if "src" in instruction: + instruction["src"] = register_map[instruction["src"]] + if "srcb" in instruction: + instruction["srcb"] = register_map[instruction["srcb"]] + + return instructions, new_registers + +def cleanup_registers(instructions, registers): + + #find all the registers that are read from. + used_registers = {} + for instruction in instructions: + if "src" in instruction: + used_registers[instruction["src"]] = None + if "srcb" in instruction: + used_registers[instruction["srcb"]] = None + + #remove them from the list of allocated registers + kept_registers = {} + for register, description in registers.iteritems(): + if register in used_registers: + kept_registers[register] = description + + #remove all instructions that read from unused registers + kept_instructions = [] + for instruction in instructions: + if "dest" in instruction: + if instruction["dest"] in kept_registers: + kept_instructions.append(instruction) + else: + kept_instructions.append(instruction) + + return reallocate_registers(kept_instructions, kept_registers) + +def parallelise(instructions): + + def modifies_register(instruction): + + """Return the register modified by this instruction if any""" + + if "dest" in instruction: + return instruction["dest"] + return None + + def uses_registers(instruction): + + """Return the registers used by this instruction if any""" + + registers = [] + for field in ["src", "srcb"]: + if field in instruction: + registers.append(instruction[field]) + return registers + + def memory_clash(a, b): + + """do instructions result in a memory clash""" + + if a["op"] in ["memory_write", "memory_write_literal"]: + return b["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"] + + if b["op"] in ["memory_write", "memory_write_literal"]: + return a["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"] + + if a["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]: + return b["op"] == a["op"] + + if b["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]: + return b["op"] == a["op"] + + def is_part_of_read(a, b): + + """requests, waits and reads with the same sequence number must not be concurrent""" + + read_instructions = ["memory_read_request", "memory_read_wait", "memory_read"] + if (a["op"] in read_instructions) and (b["op"] in read_instructions): + return a["sequence"] == b["sequence"] + return False + + def is_solitary(instruction): + + """Return True if an instruction cannot be executed in parallel with other instructions""" + + return instruction["op"] in ["read", "write", "ready", "label", "/", "%"] + + def is_jump(instruction): + + """Return True if an instruction contains a branch or jump""" + + return instruction["op"] in ["goto", "jmp_if_true", "jmp_if_false", "jmp_and_link", + "jmp_to_reg"] + + def is_dependent(instruction, frame, preceding): + + """determine whether an instruction is dependent on the outcome of: + - an instruction within the current frame + - preceding instructions not within the frame """ + + for i in frame + preceding: + if modifies_register(i) is not None: + if modifies_register(i) in uses_registers(instruction): + return True + if modifies_register(i) == modifies_register(instruction): + return True + if memory_clash(i, instruction): + return True + if is_part_of_read(i, instruction): + return True + if is_jump(i): + return True + for i in preceding: + if modifies_register(instruction) is not None: + if modifies_register(instruction) in uses_registers(i): + return True + if memory_clash(i, instruction): + return True + if is_part_of_read(i, instruction): + return True + if is_jump(instruction) and preceding: + return True + return False + + def add_instructions(frame, instructions): + + """Add more instructions to the current frame if dependencies allow.""" + + instructions_added = True + while instructions_added: + instructions_added = False + for index, instruction in enumerate(instructions): + if is_solitary(instruction): + return + for i in frame: + if is_jump(i): + return + if is_solitary(i): + return + if not is_dependent(instruction, frame, instructions[:index]): + frame.append(instructions.pop(index)) + instructions_added = True + break + + frames = [] + while instructions: + frame = [instructions.pop(0)] + add_instructions(frame, instructions) + frames.append(frame) + + return frames Index: chips2/chips/compiler/tokens.py =================================================================== --- chips2/chips/compiler/tokens.py (nonexistent) +++ chips2/chips/compiler/tokens.py (revision 2) @@ -0,0 +1,179 @@ +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +import os.path +import StringIO + +from chips.compiler.exceptions import C2CHIPError +from chips.compiler.builtins import builtins + +operators = [ + "!", "~", "+", "-", "*", "/", "//", "%", "=", "==", "<", ">", "<=", ">=", + "!=", "|", "&", "^", "||", "&&", "(", ")", "{", "}", "[", "]", ";", "<<", + ">>", ",", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", "++", + "--", "?", ":", "." +] + +class Tokens: + + """Break the input file into a stream of tokens, + provide functions to traverse the stream.""" + + def __init__(self, filename): + self.tokens = [] + self.filename = None + self.lineno = None + self.scan("built in", StringIO.StringIO(builtins)) + self.scan(filename) + + def scan(self, filename, input_file=None): + + """Convert the test file into tokens""" + self.filename = filename + + if input_file is None: + try: + input_file = open(self.filename) + except IOError: + raise C2CHIPError("Cannot open file: "+self.filename) + + token = [] + tokens = [] + self.lineno = 1 + for line in input_file: + + #include files + line = line+" " + if line.strip().startswith("#include"): + filename = self.filename + lineno = self.lineno + self.tokens.extend(tokens) + directory = os.path.abspath(self.filename) + directory = os.path.dirname(directory) + self.filename = line.strip().replace("#include", "").strip(' ><"') + self.filename = os.path.join(directory, self.filename) + self.scan(self.filename) + self.lineno = lineno + self.filename = filename + tokens = [] + continue + + newline = True + for char in line: + + if not token: + token = char + + #c style comment + elif (token + char).startswith("/*"): + if (token + char).endswith("*/"): + token = "" + else: + token += char + + #c++ style comment + elif token.startswith("//"): + if newline: + token = char + else: + token += char + + #identifier + elif token[0].isalpha(): + if char.isalnum() or char== "_": + token += char + else: + tokens.append((self.filename, self.lineno, token)) + token = char + + #number + elif token[0].isdigit(): + if char.upper() in "UXABCDEFL0123456789": + token += char + else: + tokens.append((self.filename, self.lineno, token)) + token = char + + #string literal + elif token.startswith('"'): + if char == '"' and previous_char != "\\": + token += char + tokens.append((self.filename, self.lineno, token)) + token = "" + else: + #remove dummy space from the end of a line + if newline: + token = token[:-1] + previous_char = char + token += char + + #character literal + elif token.startswith("'"): + if char == "'": + token += char + tokens.append((self.filename, self.lineno, token)) + token = "" + else: + token += char + + #operator + elif token in operators: + if token + char in operators: + token += char + else: + tokens.append((self.filename, self.lineno, token)) + token = char + + else: + token = char + + newline = False + self.lineno += 1 + + self.tokens.extend(tokens) + + def error(self, string): + + """Generate an error message (including the filename and line number)""" + + raise C2CHIPError(string + "\n", self.filename, self.lineno) + + def peek(self): + + """Return the next token in the stream, but don't consume it""" + + if self.tokens: + return self.tokens[0][2] + else: + return "" + + def get(self): + + """Return the next token in the stream, and consume it""" + + if self.tokens: + self.lineno = self.tokens[0][1] + self.filename = self.tokens[0][0] + filename, lineno, token = self.tokens.pop(0) + return token + + def end(self): + + """Return True if all the tokens have been consumed""" + + return not self.tokens + + def expect(self, expected): + + """Consume the next token in the stream, + generate an error if it is not as expected.""" + + filename, lineno, actual = self.tokens.pop(0) + if self.tokens: + self.lineno = self.tokens[0][1] + self.filename = self.tokens[0][0] + if actual == expected: + return + else: + self.error("Expected: %s, got: %s"%(expected, actual)) Index: chips2/chips/compiler/verilog_speed.py =================================================================== --- chips2/chips/compiler/verilog_speed.py (nonexistent) +++ chips2/chips/compiler/verilog_speed.py (revision 2) @@ -0,0 +1,534 @@ +#!/usr/bin/env python +"""A C to Verilog compiler""" + +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2013, Jonathan P Dawson" +__version__ = "0.1" + +def unique(l): + + """In the absence of set in older python implementations, make list values unique""" + + return dict(zip(l, l)).keys() + +def log2(frames): + + """Integer only algorithm to calculate the number of bits needed to store a number""" + + bits = 1 + power = 2 + while power < frames: + bits += 1 + power *= 2 + return bits + +def to_gray(i): + + """Convert integer to gray code""" + + return (i >> 1) ^ i + +def generate_CHIP(input_file, + name, + frames, + output_file, + registers, + memory_size_2, + memory_size_4, + initialize_memory, + memory_content_2, + memory_content_4, + no_tb_mode=False): + + """A big ugly function to crunch through all the instructions and generate the CHIP equivilent""" + + #calculate the values of jump locations + location = 0 + labels = {} + new_frames = [] + for frame in frames: + if frame[0]["op"] == "label": + labels[frame[0]["label"]] = location + else: + new_frames.append(frame) + location += 1 + frames = new_frames + + #substitue real values for labeled jump locations + for frame in frames: + for instruction in frame: + if "label" in instruction: + instruction["label"]=labels[instruction["label"]] + + #list all inputs and outputs used in the program + inputs = unique([i["input"] for frame in frames for i in frame if "input" in i]) + outputs = unique([i["output"] for frame in frames for i in frame if "output" in i]) + input_files = unique([i["file_name"] for frame in frames for i in frame if "file_read" == i["op"]]) + output_files = unique([i["file_name"] for frame in frames for i in frame if "file_write" == i["op"]]) + testbench = not inputs and not outputs and not no_tb_mode + + #Do not generate a port in testbench mode + inports = [ + ("input_" + i, 16) for i in inputs + ] + [ + ("input_" + i + "_stb", 1) for i in inputs + ] + [ + ("output_" + i + "_ack", 1) for i in outputs + ] + + outports = [ + ("output_" + i, 16) for i in outputs + ] + [ + ("output_" + i + "_stb", 1) for i in outputs + ] + [ + ("input_" + i + "_ack", 1) for i in inputs + ] + + #create list of signals + signals = [ + ("timer", 16), + ("program_counter", log2(len(frames))), + ("address_2", 16), + ("data_out_2", 16), + ("data_in_2", 16), + ("write_enable_2", 1), + ("address_4", 16), + ("data_out_4", 32), + ("data_in_4", 32), + ("write_enable_4", 1), + ] + [ + ("register_%s"%(register), definition[1]*8) for register, definition in registers.iteritems() + ] + [ + ("s_output_" + i + "_stb", 16) for i in outputs + ] + [ + ("s_output_" + i, 16) for i in outputs + ] + [ + ("s_input_" + i + "_ack", 16) for i in inputs + ] + + if testbench: + signals.append(("clk", 1)) + signals.append(("rst", 1)) + else: + inports.append(("clk", 1)) + inports.append(("rst", 1)) + + #output the code in verilog + output_file.write("//name : %s\n"%name) + output_file.write("//tag : c components\n") + for i in inputs: + output_file.write("//input : input_%s:16\n"%i) + for i in outputs: + output_file.write("//output : output_%s:16\n"%i) + output_file.write("//source_file : %s\n"%input_file) + output_file.write("///%s\n"%"".join(["=" for i in name])) + output_file.write("///\n") + output_file.write("///*Created by C2CHIP*\n\n") + + + output_file.write("// Register Allocation\n") + output_file.write("// ===================\n") + output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20))) + for register, definition in registers.iteritems(): + register_name, size = definition + output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20))) + + output_file.write(" \n`timescale 1ns/1ps\n") + output_file.write("module %s"%name) + + all_ports = [name for name, size in inports + outports] + if all_ports: + output_file.write("(") + output_file.write(",".join(all_ports)) + output_file.write(");\n") + else: + output_file.write(";\n") + + output_file.write(" integer file_count;\n") + + input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)])) + for i in input_files.values(): + output_file.write(" integer %s;\n"%i) + + output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)])) + for i in output_files.values(): + output_file.write(" integer %s;\n"%i) + + + def write_declaration(object_type, name, size, value=None): + if size == 1: + output_file.write(object_type) + output_file.write(name) + if value is not None: + output_file.write("= %s'd%s"%(size,value)) + output_file.write(";\n") + else: + output_file.write(object_type) + output_file.write("[%i:0]"%(size-1)) + output_file.write(" ") + output_file.write(name) + if value is not None: + output_file.write("= %s'd%s"%(size,value)) + output_file.write(";\n") + + for name, size in inports: + write_declaration(" input ", name, size) + + for name, size in outports: + write_declaration(" output ", name, size) + + for name, size in signals: + write_declaration(" reg ", name, size) + + memory_size_2 = int(memory_size_2) + memory_size_4 = int(memory_size_4) + if memory_size_2: + output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1)) + if memory_size_4: + output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1)) + + #generate clock and reset in testbench mode + if testbench: + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // CLOCK AND RESET GENERATION \n") + output_file.write(" // \n") + output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n") + output_file.write(" // output file can be executed directly within a verilog simulator. \n") + output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n") + output_file.write(" // the output file. \n") + output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n") + output_file.write(" // or for instantiation within a larger design.\n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" rst <= 1'b1;\n") + output_file.write(" #50 rst <= 1'b0;\n") + output_file.write(" end\n\n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + output_file.write(" clk <= 1'b0;\n") + output_file.write(" while (1) begin\n") + output_file.write(" #5 clk <= ~clk;\n") + output_file.write(" end\n") + output_file.write(" end\n\n") + + #Generate a state machine to execute the instructions + binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=", + "<=", "==", "!="] + + + if initialize_memory and (memory_content_2 or memory_content_4): + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // MEMORY INITIALIZATION \n") + output_file.write(" // \n") + output_file.write(" // In order to reduce program size, array contents have been stored into \n") + output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n") + output_file.write(" // initialized when the FPGA configures. \n") + output_file.write(" // Memory will not be re-initialized at reset. \n") + output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + for location, content in memory_content_2.iteritems(): + output_file.write(" memory_2[%s] = %s;\n"%(location, content)) + for location, content in memory_content_4.iteritems(): + output_file.write(" memory_4[%s] = %s;\n"%(location, content)) + output_file.write(" end\n\n") + + if input_files or output_files: + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // OPEN FILES \n") + output_file.write(" // \n") + output_file.write(" // Open all files used at the start of the process \n") + + output_file.write(" \n initial\n") + output_file.write(" begin\n") + for file_name, file_ in input_files.iteritems(): + output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name)) + for file_name, file_ in output_files.iteritems(): + output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name)) + output_file.write(" end\n\n") + + output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n") + output_file.write(" // FSM IMPLEMENTAION OF C PROCESS \n") + output_file.write(" // \n") + output_file.write(" // This section of the file contains a Finite State Machine (FSM) implementing\n") + output_file.write(" // the C process. In general execution is sequential, but the compiler will \n") + output_file.write(" // attempt to execute instructions in parallel if the instruction dependencies\n") + output_file.write(" // allow. Further concurrency can be achieved by executing multiple C \n") + output_file.write(" // processes concurrently within the device. \n") + + output_file.write(" \n always @(posedge clk)\n") + output_file.write(" begin\n\n") + + if memory_size_2: + output_file.write(" //implement memory for 2 byte x n arrays\n") + output_file.write(" if (write_enable_2 == 1'b1) begin\n") + output_file.write(" memory_2[address_2] <= data_in_2;\n") + output_file.write(" end\n") + output_file.write(" data_out_2 <= memory_2[address_2];\n") + output_file.write(" write_enable_2 <= 1'b0;\n\n") + + if memory_size_4: + output_file.write(" //implement memory for 4 byte x n arrays\n") + output_file.write(" if (write_enable_4 == 1'b1) begin\n") + output_file.write(" memory_4[address_4] <= data_in_4;\n") + output_file.write(" end\n") + output_file.write(" data_out_4 <= memory_4[address_4];\n") + output_file.write(" write_enable_4 <= 1'b0;\n\n") + + output_file.write(" //implement timer\n") + output_file.write(" timer <= 16'h0000;\n\n") + output_file.write(" case(program_counter)\n\n") + + #A frame is executed in each state + for location, frame in enumerate(frames): + output_file.write(" 16'd%s:\n"%to_gray(location)) + output_file.write(" begin\n") + output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1)) + for instruction in frame: + + if instruction["op"] == "literal": + output_file.write( + " register_%s <= %s;\n"%( + instruction["dest"], + instruction["literal"])) + + elif instruction["op"] == "move": + output_file.write( + " register_%s <= register_%s;\n"%( + instruction["dest"], + instruction["src"])) + + elif instruction["op"] in ["~"]: + output_file.write( + " register_%s <= ~register_%s;\n"%( + instruction["dest"], + instruction["src"])) + + elif instruction["op"] in binary_operators and "left" in instruction: + if not instruction["signed"]: + output_file.write( + " register_%s <= %s %s $unsigned(register_%s);\n"%( + instruction["dest"], + instruction["left"], + instruction["op"], + instruction["src"])) + else: + #Verilog uses >>> as an arithmetic right shift + if instruction["op"] == ">>": + instruction["op"] = ">>>" + output_file.write( + " register_%s <= %s %s $signed(register_%s);\n"%( + instruction["dest"], + instruction["left"], + instruction["op"], + instruction["src"])) + + elif instruction["op"] in binary_operators and "right" in instruction: + if not instruction["signed"]: + output_file.write( + " register_%s <= $unsigned(register_%s) %s %s;\n"%( + instruction["dest"], + instruction["src"], + instruction["op"], + instruction["right"])) + else: + #Verilog uses >>> as an arithmetic right shift + if instruction["op"] == ">>": + instruction["op"] = ">>>" + output_file.write( + " register_%s <= $signed(register_%s) %s %s;\n"%( + instruction["dest"], + instruction["src"], + instruction["op"], + instruction["right"])) + + elif instruction["op"] in binary_operators: + if not instruction["signed"]: + output_file.write( + " register_%s <= $unsigned(register_%s) %s $unsigned(register_%s);\n"%( + instruction["dest"], + instruction["src"], + instruction["op"], + instruction["srcb"])) + else: + #Verilog uses >>> as an arithmetic right shift + if instruction["op"] == ">>": + instruction["op"] = ">>>" + output_file.write( + " register_%s <= $signed(register_%s) %s $signed(register_%s);\n"%( + instruction["dest"], + instruction["src"], + instruction["op"], + instruction["srcb"])) + + elif instruction["op"] == "jmp_if_false": + output_file.write(" if (register_%s == 0)\n"%(instruction["src"])); + output_file.write(" program_counter <= %s;\n"%to_gray(instruction["label"]&0xffff)) + + elif instruction["op"] == "jmp_if_true": + output_file.write(" if (register_%s != 0)\n"%(instruction["src"])); + output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff)) + + elif instruction["op"] == "jmp_and_link": + output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff)) + output_file.write(" register_%s <= 16'd%s;\n"%( + instruction["dest"], to_gray((location+1)&0xffff))) + + elif instruction["op"] == "jmp_to_reg": + output_file.write( + " program_counter <= register_%s;\n"%instruction["src"]) + + elif instruction["op"] == "goto": + output_file.write(" program_counter <= 16'd%s;\n"%(to_gray(instruction["label"]&0xffff))) + + elif instruction["op"] == "file_read": + output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", register_%s);\n"%( + input_files[instruction["file_name"]], instruction["dest"])) + + elif instruction["op"] == "file_write": + output_file.write(" $fdisplay(%s, \"%%d\", register_%s);\n"%( + output_files[instruction["file_name"]], instruction["src"])) + + elif instruction["op"] == "read": + output_file.write(" register_%s <= input_%s;\n"%( + instruction["dest"], instruction["input"])) + output_file.write(" program_counter <= %s;\n"%to_gray(location)) + output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"]) + output_file.write( " if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%( + instruction["input"], + instruction["input"] + )) + output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"]) + output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1)) + output_file.write(" end\n") + + elif instruction["op"] == "ready": + output_file.write(" register_%s <= 0;\n"%instruction["dest"]) + output_file.write(" register_%s[0] <= input_%s_stb;\n"%( + instruction["dest"], instruction["input"])) + + elif instruction["op"] == "write": + output_file.write(" s_output_%s <= register_%s;\n"%( + instruction["output"], instruction["src"])) + output_file.write(" program_counter <= %s;\n"%to_gray(location)) + output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"]) + output_file.write( + " if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%( + instruction["output"], + instruction["output"] + )) + output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"]) + output_file.write(" program_counter <= %s;\n"%to_gray(location+1)) + output_file.write(" end\n") + + elif instruction["op"] == "memory_read_request": + output_file.write( + " address_%s <= register_%s;\n"%( + instruction["element_size"], + instruction["src"]) + ) + + elif instruction["op"] == "memory_read_wait": + pass + + elif instruction["op"] == "memory_read": + output_file.write( + " register_%s <= data_out_%s;\n"%( + instruction["dest"], + instruction["element_size"]) + ) + + elif instruction["op"] == "memory_write": + output_file.write(" address_%s <= register_%s;\n"%( + instruction["element_size"], + instruction["src"]) + ) + output_file.write(" data_in_%s <= register_%s;\n"%( + instruction["element_size"], + instruction["srcb"]) + ) + output_file.write(" write_enable_%s <= 1'b1;\n"%( + instruction["element_size"]) + ) + + elif instruction["op"] == "memory_write_literal": + output_file.write(" address_%s <= 16'd%s;\n"%( + instruction["element_size"], + instruction["address"]) + ) + output_file.write(" data_in_%s <= %s;\n"%( + instruction["element_size"], + instruction["value"]) + ) + output_file.write(" write_enable_%s <= 1'b1;\n"%( + instruction["element_size"]) + ) + + elif instruction["op"] == "assert": + output_file.write( " if (register_%s == 0) begin\n"%instruction["src"]) + output_file.write( " $display(\"Assertion failed at line: %s in file: %s\");\n"%( + instruction["line"], + instruction["file"] + )) + output_file.write( " $finish_and_return(1);\n") + output_file.write( " end\n") + + elif instruction["op"] == "wait_clocks": + output_file.write(" if (timer < register_%s) begin\n"%instruction["src"]) + output_file.write(" program_counter <= program_counter;\n") + output_file.write(" timer <= timer+1;\n") + output_file.write(" end\n") + + elif instruction["op"] == "report": + if not instruction["signed"]: + output_file.write( + ' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_%s));\n'%( + instruction["line"], + instruction["file"], + instruction["src"], + )) + else: + output_file.write( + ' $display ("%%d (report at line: %s in file: %s)", $signed(register_%s));\n'%( + instruction["line"], + instruction["file"], + instruction["src"], + )) + + elif instruction["op"] == "stop": + #If we are in testbench mode stop the simulation + #If we are part of a larger design, other C programs may still be running + for file_ in input_files.values(): + output_file.write(" $fclose(%s);\n"%file_) + for file_ in output_files.values(): + output_file.write(" $fclose(%s);\n"%file_) + if testbench: + output_file.write(' $finish;\n') + output_file.write(" program_counter <= program_counter;\n") + output_file.write(" end\n\n") + + output_file.write(" endcase\n") + + #Reset program counter and control signals + output_file.write(" if (rst == 1'b1) begin\n") + output_file.write(" program_counter <= 0;\n") + for i in inputs: + output_file.write(" s_input_%s_ack <= 0;\n"%(i)) + for i in outputs: + output_file.write(" s_output_%s_stb <= 0;\n"%(i)) + output_file.write(" end\n") + output_file.write(" end\n") + for i in inputs: + output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i)) + for i in outputs: + output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i)) + output_file.write(" assign output_%s = s_output_%s;\n"%(i, i)) + output_file.write("\nendmodule\n") + + return inputs, outputs
chips2/chips/compiler/verilog_speed.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/chips/compiler/parser.py,cover =================================================================== --- chips2/chips/compiler/parser.py,cover (nonexistent) +++ chips2/chips/compiler/parser.py,cover (revision 2) @@ -0,0 +1,671 @@ +> __author__ = "Jon Dawson" +> __copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +> __version__ = "0.1" + +> from parse_tree import * +> from tokens import Tokens +> from allocator import Allocator + +> def optimise_if(if_statement): +> try: +> if value(if_statement.expression): +> return if_statement.true_statement +> elif if_statement.false_statement: +> return if_statement.false_statement +> else: +> null_instruction = Block() +> null_instruction.statements = [] +> return null_instruction +> except NotConstant: +> return if_statement + +> class Parser: + +> """Turn the C input file into a tree of expressions and statements.""" + +> def __init__(self, input_file, reuse): +> self.scope = {} +> self.function = None +> self.loop = None +> self.tokens = Tokens(input_file) +> self.allocator = Allocator(reuse) +> self.structs = [] + +> def parse_process(self): +> process = Process() +> process.allocator = self.allocator +> process.inputs = [] +> process.outputs = [] +> process.functions = [] +> while not self.tokens.end(): +> if self.tokens.peek() == "struct": +> self.parse_define_struct() +> elif self.tokens.peek() == "typedef": +> self.parse_typedef_struct() +> else: +> process.functions.append(self.parse_function()) +> process.main = self.main +> return process + +> def parse_function(self): +> function = Function() +> function.allocator = self.allocator +> stored_scope = self.scope +> type_ = self.tokens.get() +> name = self.tokens.get() + + #check if it is a global declaration +> if self.tokens.peek() != "(": +> if type_ not in ["int", "short", "long", "char"] + self.structs: +! self.tokens.error("unknown type") +> return self.parse_global_declaration(type_, name) + + #otherwise continue parsing a function +> self.tokens.expect("(") +> function.name = name +> function.type_ = type_ +> function.return_address = self.allocator.new(function.name+" return address") +> if type_ not in ["int", "short", "long", "char", "void"]: +! self.tokens.error("unknown type") +> if type_ != "void": +> function.return_value = self.allocator.new(function.name+" return value") +> function.arguments = [] +> while self.tokens.peek() != ")": +> type_ = self.tokens.get() +> if type_ not in ["int", "short", "long", "char"]: +! self.tokens.error("unknown type") +> argument = self.tokens.get() +> if self.tokens.peek() == "[": +> self.tokens.expect("[") +> self.tokens.expect("]") +> type_+="[]" +> function.arguments.append(Argument(argument, type_, self)) +> if self.tokens.peek() == ",": +> self.tokens.expect(",") +> else: +> break +> self.tokens.expect(")") +> self.function = function +> function.statement = self.parse_statement() +> if type_ != "void" and not hasattr(function, "return_statement"): +> self.tokens.error("Function must have a return statement") +> self.function = None +> self.scope = stored_scope +> self.scope[function.name] = function + #main thread is last function +> self.main = function +> return function + +> def parse_break(self): +> break_ = Break() +> break_.loop = self.loop +> self.tokens.expect("break") +> self.tokens.expect(";") +> return break_ + +> def parse_continue(self): +> continue_ = Continue() +> continue_.loop = self.loop +> self.tokens.expect("continue") +> self.tokens.expect(";") +> return continue_ + +> def parse_return(self): +> return_ = Return() +> return_.function = self.function +> self.function.return_statement = return_ +> self.tokens.expect("return") +> if hasattr(self.function, "return_value"): +> return_.expression = self.parse_expression() +> self.tokens.expect(";") +> return return_ + +> def parse_assert(self): +> assert_ = Assert() +> assert_.allocator = self.allocator +> self.tokens.expect("assert") +> self.tokens.expect("(") +> assert_.expression = self.parse_expression() +> self.tokens.expect(")") +> self.tokens.expect(";") +> assert_.line = self.tokens.lineno +> assert_.filename = self.tokens.filename +> return assert_ + +> def parse_report(self): +> report_ = Report() +> report_.allocator = self.allocator +> self.tokens.expect("report") +> self.tokens.expect("(") +> report_.expression = self.parse_expression() +> self.tokens.expect(")") +> self.tokens.expect(";") +> report_.line = self.tokens.lineno +> report_.filename = self.tokens.filename +> return report_ + +> def parse_wait_clocks(self): +> wait_clocks = WaitClocks() +> wait_clocks.allocator = self.allocator +> self.tokens.expect("wait_clocks") +> self.tokens.expect("(") +> wait_clocks.expression = self.parse_expression() +> self.tokens.expect(")") +> self.tokens.expect(";") +> wait_clocks.line = self.tokens.lineno +> return wait_clocks + +> def parse_statement(self): +> if self.tokens.peek() in ["int", "short", "long", "char"] + self.structs: +> return self.parse_compound_declaration() +> elif self.tokens.peek() == "struct": +> return self.parse_struct_declaration() +> elif self.tokens.peek() == "if": +> return self.parse_if() +> elif self.tokens.peek() == "while": +> return self.parse_while() +> elif self.tokens.peek() == "for": +> return self.parse_for() +> elif self.tokens.peek() == "return": +> return self.parse_return() +> elif self.tokens.peek() == "break": +> return self.parse_break() +> elif self.tokens.peek() == "continue": +> return self.parse_continue() +> elif self.tokens.peek() == "{": +> return self.parse_block() +> elif self.tokens.peek() == "assert": +> return self.parse_assert() +> elif self.tokens.peek() == "report": +> return self.parse_report() +> elif self.tokens.peek() == "switch": +> return self.parse_switch() +> elif self.tokens.peek() == "case": +> return self.parse_case() +> elif self.tokens.peek() == "default": +> return self.parse_default() +> elif self.tokens.peek() == "wait_clocks": +> return self.parse_wait_clocks() +> else: +> expression = self.parse_discard() +> self.tokens.expect(";") +> return expression + +> def parse_discard(self): +> return DiscardExpression(self.parse_expression(), self.allocator) + +> def parse_assignment(self): +> assignment_operators = [ +> "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", +> "++", "--" +> ] +> lvalue = self.parse_ternary_expression() +> if self.tokens.peek() in assignment_operators: +> if not hasattr(lvalue, "declaration"): +> self.tokens.error( +> "left hand operand of assignment is not modifiable" +> ) +> operator = self.tokens.get() +> if operator == "=": +> expression = self.parse_ternary_expression() +> elif operator in ["++", "--"]: +> expression = Binary( +> operator[:-1], +> lvalue, +> Constant(1), +> self.allocator +> ) +> else: +> expression = Binary( +> operator[:-1], +> lvalue, +> self.parse_ternary_expression(), +> self.allocator +> ) +> if lvalue.type_ != expression.type_: +> self.tokens.error( +> "type mismatch in assignment" +> ) +> return Assignment(lvalue, expression, self.allocator) +> else: +> return lvalue + + +> def parse_if(self): +> if_ = If() +> if_.allocator = self.allocator +> self.tokens.expect("if") +> self.tokens.expect("(") +> if_.expression = self.parse_expression() +> if if_.expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "if statement conditional must be an integer like expression" +> ) +> self.tokens.expect(")") +> if_.true_statement = self.parse_statement() +> if self.tokens.peek() == "else": +> self.tokens.expect("else") +> if_.false_statement = self.parse_statement() +> else: +> if_.false_statement = None +> return optimise_if(if_) + +> def parse_switch(self): +> switch = Switch() +> switch.cases = {} +> self.tokens.expect("switch") +> self.tokens.expect("(") +> expression = self.parse_expression() +> if expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "switch statement expression must be an integer like expression" +> ) +> self.tokens.expect(")") +> stored_loop = self.loop +> self.loop = switch +> statement = self.parse_statement() +> self.loop = stored_loop +> switch.expression = expression +> switch.allocator = self.allocator +> switch.statement = statement +> return switch + +> def parse_case(self): +> self.tokens.expect("case") +> expression = self.parse_expression() +> if expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "case expression must be an integer like expression" +> ) +> self.tokens.expect(":") +> try: +> expression = value(expression) +> case = Case() +> self.loop.cases[expression] = case +> except NotConstant: +> self.tokens.error("case expression must be constant") +> except AttributeError: +> self.tokens.error( +> "case statements may only be use inside a switch statment" +> ) +> return case + +> def parse_default(self): +> self.tokens.expect("default") +> self.tokens.expect(":") +> default = Default() +> if not hasattr(self.loop, "cases"): +> self.tokens.error( +> "default statements may only be used inside a switch statment" +> ) +> if hasattr(self.loop, "default"): +> self.tokens.error( +> "A switch statement may only have one default statement" +> ) +> self.loop.default=default +> return default + +> def parse_while(self): +> loop = Loop() +> self.tokens.expect("while") +> self.tokens.expect("(") +> expression = self.parse_expression() +> self.tokens.expect(")") +> stored_loop = self.loop +> self.loop = loop +> statement = self.parse_statement() +> self.loop = stored_loop + +> if_ = If() +> break_ = Break() +> break_.loop = loop +> if_.allocator = self.allocator +> if expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "if statement conditional must be an integer like expression" +> ) +> if_.expression = expression +> if_.false_statement = break_ +> if_.true_statement = statement + +> loop.statement = optimise_if(if_) +> return loop + +> def parse_for(self): +> for_ = For() +> for_.allocator = self.allocator +> self.tokens.expect("for") +> self.tokens.expect("(") +> if self.tokens.peek() != ";": +> for_.statement1 = self.parse_discard() +> self.tokens.expect(";") +> if self.tokens.peek() != ";": +> for_.expression = self.parse_expression() +> if for_.expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "for statement conditional must be an integer like expression" +> ) +> self.tokens.expect(";") +> if self.tokens.peek() != ")": +> for_.statement2 = self.parse_discard() +> self.tokens.expect(")") +> stored_loop = self.loop +> self.loop = for_ +> for_.statement3 = self.parse_statement() +> self.loop = stored_loop +> return for_ + +> def parse_block(self): +> block = Block() +> stored_scope = self.scope +> self.tokens.expect("{") +> block.statements = [] +> while self.tokens.peek() != "}": +> block.statements.append(self.parse_statement()) +> self.tokens.expect("}") +> self.scope = stored_scope +> return block + +> def parse_struct_body(self): +> self.tokens.expect("{") +> members = {} +> while self.tokens.peek() != "}": +> type_ = self.tokens.get() +> name = self.tokens.get() +> members[name] = self.parse_declaration(type_, name) +> self.tokens.expect(";") +> self.tokens.expect("}") +> return members + +> def parse_typedef_struct(self): +> self.tokens.expect("typedef") +> self.tokens.expect("struct") +> declaration = StructDeclaration(self.parse_struct_body()) +> name = self.tokens.get() +> self.tokens.expect(";") +> self.scope[name] = declaration +> self.structs.append(name) + +> def parse_define_struct(self): +> self.tokens.expect("struct") +> name = self.tokens.get() +> declaration = StructDeclaration(self.parse_struct_body()) +> self.tokens.expect(";") +> self.scope[name] = declaration + +> def parse_struct_declaration(self): +> self.tokens.expect("struct") +> struct_name = self.tokens.get() +> name = self.tokens.get() +> self.tokens.expect(";") +> instance = self.scope[struct_name].instance() +> self.scope[name] = instance +> return instance + +> def parse_global_declaration(self, type_, name): +> instances = [] +> while True: +> instance = self.parse_declaration(type_, name).instance() +> self.scope[name] = instance +> instances.append(instance) +> if self.tokens.peek() == ",": +> self.tokens.expect(",") +> else: +> break +> name = self.tokens.get() +> self.tokens.expect(";") +> return CompoundDeclaration(instances) + +> def parse_compound_declaration(self): +> type_ = self.tokens.get() +> instances = [] +> while True: +> name = self.tokens.get() +> instance = self.parse_declaration(type_, name).instance() +> self.scope[name] = instance +> instances.append(instance) +> if self.tokens.peek() == ",": +> self.tokens.expect(",") +> else: +> break +> name = None +> self.tokens.expect(";") +> return CompoundDeclaration(instances) + +> def parse_declaration(self, type_, name): + #struct declaration +> if type_ in self.structs: +> declaration = self.scope[type_] +> elif type_ in ["int", "short", "long", "char"]: + #array declaration +> if self.tokens.peek() == "[": +> size = None +> self.tokens.expect("[") +> if self.tokens.peek() != "]": +> size = self.tokens.get() +> self.tokens.expect("]") +> initializer = None +> if self.tokens.peek() == "=": +> self.tokens.expect("=") +> initializer = self.tokens.get() +> initializer = [ord(i) for i in initializer.strip('"')] + [0] +> size = len(initializer) +> if size is None: +> self.tokens.error("array size must be specified if not initialized") +> type_+="[]" +> declaration = ArrayDeclaration(self.allocator, size, type_, initializer) + + #simple variable declaration +> else: +> if self.tokens.peek() == "=": +> self.tokens.expect("=") +> initializer = self.parse_ternary_expression() +> else: +> initializer = Constant(0) +> declaration = VariableDeclaration( +> self.allocator, +> initializer, +> name, +> type_ +> ) + +> return declaration + +> def parse_expression(self): +> expression = self.parse_assignment() +> return expression + +> def parse_ternary_expression(self): +> expression = constant_fold(self.parse_or_expression()) +> while self.tokens.peek() in ["?"]: +> self.tokens.expect("?") +> true_expression = constant_fold(self.parse_or_expression()) +> self.tokens.expect(":") +> false_expression = constant_fold(self.parse_or_expression()) +> expression = OR(AND(expression, true_expression), false_expression) +> return expression + +> def parse_or_expression(self): +> expression = self.parse_and_expression() +> while self.tokens.peek() in ["||"]: +> self.tokens.expect("||") +> expression = OR(expression, self.parse_and_expression()) +> return expression + +> def parse_and_expression(self): +> expression = self.parse_binary_expression(["|"]) +> while self.tokens.peek() in ["&&"]: +> self.tokens.expect("&&") +> expression = AND(expression, self.parse_binary_expression(["|"])) +> return expression + +> def parse_binary_expression(self, operators): +> operator_precedence = { +> "|": ["^"], +> "^": ["&"], +> "&": ["==", "!="], +> "==": ["<", ">", "<=", ">="], +> "<": ["<<", ">>"], +> "<<": ["+", "-"], +> "+": ["*", "/", "%"], +> } +> if operators[0] not in operator_precedence: +> expression = self.parse_unary_expression() +> while self.tokens.peek() in operators: +> expression = Binary( +> self.tokens.get(), +> expression, +> self.parse_unary_expression(), +> self.allocator +> ) +> return expression +> else: +> next_operators = operator_precedence[operators[0]] +> expression = self.parse_binary_expression(next_operators) +> while self.tokens.peek() in operators: +> expression = Binary( +> self.tokens.get(), +> expression, +> self.parse_binary_expression(next_operators), +> self.allocator +> ) +> return expression + +> def parse_unary_expression(self): +> if self.tokens.peek() == "!": +> operator = self.tokens.get() +> expression = self.parse_paren_expression() +> return Binary("==", expression, Constant(0), self.allocator) +> elif self.tokens.peek() == "-": +> operator = self.tokens.get() +> expression = self.parse_paren_expression() +> return Binary("-", Constant(0), expression, self.allocator) +> elif self.tokens.peek() == "~": +> operator = self.tokens.get() +> expression = self.parse_paren_expression() +> return Unary("~", expression) +> else: +> return self.parse_paren_expression() + +> def parse_paren_expression(self): +> if self.tokens.peek() == "(": +> self.tokens.expect("(") +> expression = self.parse_expression() +> self.tokens.expect(")") +> else: +> expression = self.parse_number_or_variable() +> return expression + +> def parse_number_or_variable(self): +> if self.tokens.peek()[0].isalpha(): +> name = self.tokens.get() +> if self.tokens.peek() == "(": +> return self.parse_function_call(name) +> else: +> return self.parse_variable(name) +> else: +> return self.parse_number() + +> def parse_input(self, name): +> input_name = name.replace("input_", "") +> self.tokens.expect("(") +> self.tokens.expect(")") +> return Input(input_name) + +> def parse_ready(self, name): +> input_name = name.replace("ready_", "") +> self.tokens.expect("(") +> self.tokens.expect(")") +> return Ready(input_name) + +> def parse_output(self, name): +> output_name = name.replace("output_", "") +> self.tokens.expect("(") +> expression = self.parse_expression() +> self.tokens.expect(")") +> return Output(output_name, expression) + +> def parse_function_call(self, name): +> if name.startswith("input_"): +> return self.parse_input(name) +> if name.startswith("ready_"): +> return self.parse_ready(name) +> if name.startswith("output_"): +> return self.parse_output(name) +> function_call = FunctionCall() +> function_call.arguments = [] +> self.tokens.expect("(") +> while self.tokens.peek() != ")": +> function_call.arguments.append(self.parse_expression()) +> if self.tokens.peek() == ",": +> self.tokens.expect(",") +> else: +> break +> self.tokens.expect(")") + +> if name not in self.scope: +> self.tokens.error("Unknown function: %s"%name) + +> function_call.function = self.scope[name] +> function_call.type_ = function_call.function.type_ +> required_arguments = len(function_call.function.arguments) +> actual_arguments = len(function_call.arguments) +> if required_arguments != actual_arguments: +> self.tokens.error("Function %s takes %s arguments %s given."%( +> name, +> len(function_call.function.arguments), +> len(function_call.arguments) +> )) +> required_arguments = function_call.function.arguments +> actual_arguments = function_call.arguments +> for required, actual in zip(required_arguments, actual_arguments): +> if required.type_ != actual.type_: +> self.tokens.error("Type mismatch expected type : %s got: %s."%( +> required.type_, +> actual.type_ +> )) + + +> return function_call + +> def parse_number(self): +> token = self.tokens.get() +> if token.startswith("'"): +> try: +> token = eval(token) +> value = ord(token) +! except SyntaxError: +! self.tokens.error("%s is not a character literal"%token) +> else: +> try: +> value = int(eval(token)) +> except SyntaxError: +> self.tokens.error("%s is not an integer literal"%token) +> return Constant(value) + +> def parse_variable(self, name): +> if name not in self.scope: +> self.tokens.error("Unknown variable: %s"%name) +> instance = self.scope[name] +> return self.parse_variable_array_struct(instance) + +> def parse_variable_array_struct(self, instance): +> if instance.type_ in ["int", "short", "long", "char"]: +> return Variable(instance, self.allocator) +> elif instance.type_.endswith("[]"): +> if self.tokens.peek() == "[": +> self.tokens.expect("[") +> index_expression = self.parse_expression() +> self.tokens.expect("]") +> if index_expression.type_ not in ["int", "short", "long", "char"]: +> self.tokens.error( +> "array indices must be an integer like expression" +> ) +> return ArrayIndex(instance, index_expression, self.allocator) +> else: +> return Array(instance, self.allocator) +> elif instance.type_ == "struct": +> self.tokens.expect(".") +> member = self.tokens.get() +> instance = instance.members[member] +> return self.parse_variable_array_struct(instance) Index: chips2/COPYING.txt =================================================================== --- chips2/COPYING.txt (nonexistent) +++ chips2/COPYING.txt (revision 2) @@ -0,0 +1,19 @@ +Copyright (c) 2012 Jonathan P Dawson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Index: chips2/setup.py =================================================================== --- chips2/setup.py (nonexistent) +++ chips2/setup.py (revision 2) @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +from distutils.core import setup + +setup(name="Chips", + version="0.1.2", + description="Design hardware with Python", + long_description="""\ + +Chips +----- + +The Chips library allows hardware devices to be designed in python and C + +Features + +- Design components in C + +- Connect components together using a python API to generate a chip + +- Automatic generation of synthesisable Verilog. + +""", + + author="Jon Dawson", + author_email="chips@jondawson.org.uk", + url="http://github.com/dawsonjon/Chips-2.0", + keywords=["Verilog", "FPGA", "C", "HDL", "Synthesis"], + classifiers = [ + "Programming Language :: Python", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "Development Status :: 3 - Alpha", + "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Topic :: Software Development :: Embedded Systems", + "Topic :: Software Development :: Code Generators", + ], + packages=[ + "chips", + "chips.compiler", + "chips.api" + ], + scripts=[ + "c2verilog" + ] +) +
chips2/setup.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/test_suite/slow_consumer.c =================================================================== --- chips2/test_suite/slow_consumer.c (nonexistent) +++ chips2/test_suite/slow_consumer.c (revision 2) @@ -0,0 +1,23 @@ +void consumer(){ + wait_clocks(1000); + assert(input_a()==1); + wait_clocks(1000); + assert(input_a()==2); + wait_clocks(1000); + assert(input_a()==3); + wait_clocks(1000); + assert(input_a()==4); + wait_clocks(1000); + assert(input_a()==5); + wait_clocks(1000); + assert(input_a()==6); + wait_clocks(1000); + assert(input_a()==7); + wait_clocks(1000); + assert(input_a()==8); + wait_clocks(1000); + assert(input_a()==9); + wait_clocks(1000); + assert(input_a()==10); + report(1); +} Index: chips2/test_suite/test.c =================================================================== --- chips2/test_suite/test.c (nonexistent) +++ chips2/test_suite/test.c (revision 2) @@ -0,0 +1,10 @@ + +int main(){ + assert(0); + return 0; +} + +//last function is always main +int real_main(){ + return 0; +} Index: chips2/test_suite/interconnect.py =================================================================== --- chips2/test_suite/interconnect.py (nonexistent) +++ chips2/test_suite/interconnect.py (revision 2) @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +from chips.api.api import * +import sys + + +my_chip = Chip("interconnect") + +wire = Wire(my_chip) +Component("producer.c")(my_chip, outputs={"z":wire}) +Component("consumer.c")(my_chip, inputs={"a":wire}) + +my_chip.generate_verilog() +my_chip.generate_testbench()
chips2/test_suite/interconnect.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/test_suite/test_include.c =================================================================== --- chips2/test_suite/test_include.c (nonexistent) +++ chips2/test_suite/test_include.c (revision 2) @@ -0,0 +1,3 @@ +int include_function(){ + return 12; +} Index: chips2/test_suite/producer.c =================================================================== --- chips2/test_suite/producer.c (nonexistent) +++ chips2/test_suite/producer.c (revision 2) @@ -0,0 +1,12 @@ +void producer(){ + output_z(1); + output_z(2); + output_z(3); + output_z(4); + output_z(5); + output_z(6); + output_z(7); + output_z(8); + output_z(9); + output_z(10); +} Index: chips2/test_suite/.gitignore =================================================================== --- chips2/test_suite/.gitignore (nonexistent) +++ chips2/test_suite/.gitignore (revision 2) @@ -0,0 +1,4 @@ +main +real_main +test +arbiter Index: chips2/test_suite/slow_producer.c =================================================================== --- chips2/test_suite/slow_producer.c (nonexistent) +++ chips2/test_suite/slow_producer.c (revision 2) @@ -0,0 +1,22 @@ +void producer(){ + wait_clocks(1000); + output_z(1); + wait_clocks(1000); + output_z(2); + wait_clocks(1000); + output_z(3); + wait_clocks(1000); + output_z(4); + wait_clocks(1000); + output_z(5); + wait_clocks(1000); + output_z(6); + wait_clocks(1000); + output_z(7); + wait_clocks(1000); + output_z(8); + wait_clocks(1000); + output_z(9); + wait_clocks(1000); + output_z(10); +} Index: chips2/test_suite/main.v =================================================================== --- chips2/test_suite/main.v (nonexistent) +++ chips2/test_suite/main.v (revision 2) @@ -0,0 +1,177 @@ +//name : main +//tag : c components +//input : input_a:16 +//input : input_b:16 +//input : input_select:16 +//output : output_z:16 +//source_file : test.c +///==== +/// +///*Created by C2CHIP* + +// Register Allocation +// =================== +// Register Name Size +// 0 main return address 2 +// 1 temporary_register 2 + +`timescale 1ns/1ps +module main(input_a,input_b,input_select,input_a_stb,input_b_stb,input_select_stb,output_z_ack,clk,rst,output_z,output_z_stb,input_a_ack,input_b_ack,input_select_ack); + integer file_count; + input [15:0] input_a; + input [15:0] input_b; + input [15:0] input_select; + input input_a_stb; + input input_b_stb; + input input_select_stb; + input output_z_ack; + input clk; + input rst; + output [15:0] output_z; + output output_z_stb; + output input_a_ack; + output input_b_ack; + output input_select_ack; + reg [15:0] timer; + reg [3:0] program_counter; + reg [15:0] address_2; + reg [15:0] data_out_2; + reg [15:0] data_in_2; + reg write_enable_2; + reg [15:0] address_4; + reg [31:0] data_out_4; + reg [31:0] data_in_4; + reg write_enable_4; + reg [15:0] register_0; + reg [15:0] register_1; + reg [15:0] s_output_z_stb; + reg [15:0] s_output_z; + reg [15:0] s_input_a_ack; + reg [15:0] s_input_b_ack; + reg [15:0] s_input_select_ack; + + ////////////////////////////////////////////////////////////////////////////// + // FSM IMPLEMENTAION OF C PROCESS + // + // This section of the file contains a Finite State Machine (FSM) implementing + // the C process. In general execution is sequential, but the compiler will + // attempt to execute instructions in parallel if the instruction dependencies + // allow. Further concurrency can be achieved by executing multiple C + // processes concurrently within the device. + + always @(posedge clk) + begin + + //implement timer + timer <= 16'h0000; + + case(program_counter) + + 16'd0: + begin + program_counter <= 16'd1; + program_counter <= 16'd3; + register_0 <= 16'd1; + end + + 16'd1: + begin + program_counter <= 16'd3; + program_counter <= program_counter; + end + + 16'd3: + begin + program_counter <= 16'd2; + register_1 <= input_select; + program_counter <= 3; + s_input_select_ack <= 1'b1; + if (s_input_select_ack == 1'b1 && input_select_stb == 1'b1) begin + s_input_select_ack <= 1'b0; + program_counter <= 16'd2; + end + end + + 16'd2: + begin + program_counter <= 16'd6; + if (register_1 == 0) + program_counter <= 4; + end + + 16'd6: + begin + program_counter <= 16'd7; + register_1 <= input_a; + program_counter <= 6; + s_input_a_ack <= 1'b1; + if (s_input_a_ack == 1'b1 && input_a_stb == 1'b1) begin + s_input_a_ack <= 1'b0; + program_counter <= 16'd7; + end + end + + 16'd7: + begin + program_counter <= 16'd5; + s_output_z <= register_1; + program_counter <= 7; + s_output_z_stb <= 1'b1; + if (s_output_z_stb == 1'b1 && output_z_ack == 1'b1) begin + s_output_z_stb <= 1'b0; + program_counter <= 5; + end + end + + 16'd5: + begin + program_counter <= 16'd4; + program_counter <= 16'd13; + end + + 16'd4: + begin + program_counter <= 16'd12; + register_1 <= input_b; + program_counter <= 4; + s_input_b_ack <= 1'b1; + if (s_input_b_ack == 1'b1 && input_b_stb == 1'b1) begin + s_input_b_ack <= 1'b0; + program_counter <= 16'd12; + end + end + + 16'd12: + begin + program_counter <= 16'd13; + s_output_z <= register_1; + program_counter <= 12; + s_output_z_stb <= 1'b1; + if (s_output_z_stb == 1'b1 && output_z_ack == 1'b1) begin + s_output_z_stb <= 1'b0; + program_counter <= 13; + end + end + + 16'd13: + begin + program_counter <= 16'd15; + program_counter <= register_0; + end + + endcase + if (rst == 1'b1) begin + program_counter <= 0; + s_input_a_ack <= 0; + s_input_b_ack <= 0; + s_input_select_ack <= 0; + s_output_z_stb <= 0; + end + end + assign input_a_ack = s_input_a_ack; + assign input_b_ack = s_input_b_ack; + assign input_select_ack = s_input_select_ack; + assign output_z_stb = s_output_z_stb; + assign output_z = s_output_z; + +endmodule Index: chips2/test_suite/.coverage =================================================================== --- chips2/test_suite/.coverage (nonexistent) +++ chips2/test_suite/.coverage (revision 2) @@ -0,0 +1,29 @@ +€}q(U collectorqU +coverage v3.4qUlinesq}q(U)/usr/share/pyshared/coverage/collector.pyq]q(KèKéKëKöK÷eUB/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/optimizer.pyq]q (KKKKK KKKKKKKKKKKKKKK K"K#K$K&K(K)K*K+K,K-K.K0K1K2K3K4K5K6K8K:K=K>K?K@KAKBKEKFKGKHKKKLKMKNKOKQKSKUKWK[K\K]K_KcKdKeKfKgKiKmKnKpKqKsKtKvKwKyK}K~KK€K‚K†KˆKŒKKK•K–K—K˜K™KšK›KœKKžKŸK K¡K¢K£K¤K¥K§K©KªK«K­K±K²K³K´KµK¶K·K¸K¹KºK»K¼K½K¾K¿KÁKÂKÃKÄKÅKÇeUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/compiler.pyq +]q (KKKKKK K K K +KKKKKKKKKKKKKK K!K"K#K$K%K&K'K(K)K*K+K,K-K.K/K0K5K6K7K8K9K:K;K>K?K@KAKBKCKDKEKFKGKHKIKJKKKLKNKOKPKQKTeU?/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/tokens.pyq ]q +(KKKKKKK K K +KKKKKKKKKKKK!K#K$K%K)K*K+K,K/K0K1K2K3K4K5K6K7K8K9K:K;KK?KAKBKEKFKGKIKLKMKNKPKSKTKUKWKXK[K\K]K_K`KcKdKeKfKgKjKlKmKpKqKrKsKtKvKyKzK{K}K~KKƒK„K†KˆKŒKŽK’K“K—K›KœKKžKŸK¡K¥K§K¬K­K®K¯K°K±K³eUF/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/verilog_speed.pyq]q(KKKKKK KKKKKKKKKK)K.K/K0K1K2K3K5K6K7K:K;KM?M@MCMEMFMGMHMIMJMLMMMNMOMPMQMRMSMVMWMXMYMZM[M\M]M_M`MaMbMcMdMeMfMiMjMkMlMmMnMoMpMrMsMtMvMwMxMzM{M|M}MM€MMƒM„M†MŠMŽMMM‘M’M“M”M•M—M˜M™M›MœMMžM M¡M¢M£M¤M¥M¦M§M¨MªM«M¬M®M¯M°M±M²MµM¶M¸M¹MºM»M¼M¿MÀMÁMÂMÄMÅMÆMÈMÉMÌMÍMÎMÏMÑMÒMÓMÕMÖMÙMÚMÛMÜMÝMßMàMâMãMäMåMæMèMéMñMòMóMôMõMøMûMýMÿMMMMMMM M +M M M +MMMMMMMMeUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/__init__.pyq]qKaUC/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/parse_tree.pyq]q(KKKKKKK K +KKKKKKKK"K$K%K&K'K(K)K*K+K,K-K.K/K0K1K3K4K5K6K7K8K9K:KM?M@MAMCMDMEMFMGMIMJMSMTMUMVMWMXMYMZM[M]M^M_M`MbMcMdMeMfMpMqMsMtMvMwMxMyMzM{M|M}MM€MM‚MƒM„M†M‡MˆMŠMŒMMŽMMM‘M’M“M”M–M—M˜M™MšM›MœMMžMŸM M¡M¢M£M¤M¥M¦M§M¨M©MªM«M¬M­M®M¯M°M±M²M´MµM·M¸MºM»M¼M½M¾M¿MÀMÁMÃMÄMÅMÆMÇMÈMÊMËMÍMÎMÏMÐMÑMÒMÓMÔMÕMÖM×MØMÙMÛMÜMÝMÞMßMàMâMãMäMåMçMèMîMóMôMõMöM÷MøMúMûMýMþMMMM M +M M MMMMMMMMMMMMMMMMM M"M#M$M%M&M'M(M)M*M,M-M.M/M0M1M2M3M4M5M6M7M8M9M:M;M<M=M>M?M@MAMBMCMDMEMGMHMIMJMKMLMMMNMPMQMRMSMTMUMVMXMYMZM[M\M]M^M_MaMcMeMfMgMiMjMkMlMmMoMqMrMsMtMuMvMwMxMzM{M|M}M~MM€M‚MƒM„M…M†M‡MˆM‰MŠM‹MŒMMŽMMM’M”M•M–M—M˜M™M›MœMMŸM eUB/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/allocator.pyq]q(KKKKKK K +K K K +KKKKKKKKKKKKKKKK K$K%K&K'K(K)K*K+K-K.K/eUE/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/verilog_area.pyq]q(K K +KKKKKKKKKKK K"K&K'K)K+K/K0K1K2K3K4K5K6K7K8K9K:K;KK?K@KBKCKDKEKGKHKJKNKOKPKQKRKSKTKUKVKWKXKYKZK\K]K_K`KbKcKeKfKhKiKkKlKnKoKqKrKtKuKwKxKyK{K|K}K~K€KK‚K„K…K†KˆK‰K‹KŒKKŽKKK’K”K™KšK›KœKKžK K¡K¢K¥K¦K§K©K«K°K±K²K³K´K»K¼KÃKÄKëKìKïKðKñKóKôKöMMMMM M +M M M +MMMMMMMMMMMMMMM M!M"M$M%M'M(M)M*M+M-M/M1M2M5M6M:M;M<M=M>M@MBMCMDMEMFMHMJMKMMMNMPMQMSMTMUMVMWMXMZM[M_MaMbMcMdMeMfMgMhMiMkMlMmMnMoMqMrMsMtMuMvMwMzM{M~M€MM‚MƒM„M…M†M‡M‰MŠM‹MŒMMM’M“M”M•M–M—M˜M™MšMœMMžMŸM M¡M¢M£M¤M¥M¦M§M¨MªM¹MºM»M¼M¾M¿MÁMÂMÃMÄMÅMÆMÇMÉMÊMËMÌMÍMÎMÏMÑMÓMÔMÕMÖM×MØMÙMÚMÛMÜMÝMÞMßMàMáMâMãMäMåMæMèMéMêMëMìMíMîMïMðMñMóMôMõMöMùMûMüMýMþMÿMMMMMMMM M +M M M +MMMMMMMMMMMMMMMM M!M#M$M%M'M(M)M*M+M,M.M/M0M1M2M3M4M6M7M8M9M:M;M<M=M>M?MAMBMCMDMEMFMGMHMIMJMLMMMNMOMPMQMRMSMTMUMWMXMYMZM[M\M]M^M`MaMbMcMdMeMfMgMiMqMxMyMzM{M|M}M~MMM‚MƒM„M…M†M‡MˆMŠM‹MŒMMŽMMM‘M’M”M•M–M—M˜M™M›MœMžMŸM M¡M¢M£M¤M¦M§M¨M©MªM«M¬M­M®M¯M±M²M³M´MµM¶M·M¸M¹MºM¼M½M¾M¿MÀMÁMÂMÃMÄMÆMÇMÈMÉMÎMÏMÐMÑMÓMÖM×MØMÚMÜMÝMÞMßMàMáMäMåMçMéMêMëMìMíMîMïMðMñMòMóMõMöM÷MøMùMúMûMüMýMÿMMMMMMMMMM M M +MMMMMMMMMMMMMMMMMeU(/usr/share/pyshared/coverage/execfile.pyq]q(KKKKKK!K"K#K$K&K(K)K*K+K/K1K4K5K6K9KDKGKHeU0/media/sdb1/Projects/SP605_DEMO/chips2/c2verilogq]q(KKKKKK K K +KKKK!K"K#K$K%K(K)K*K+K,K.eU'/usr/share/pyshared/coverage/control.pyq]qMeaU8/media/sdb1/Projects/SP605_DEMO/chips2/chips/__init__.pyq]qKaU?/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/parser.pyq ]q!(KKKKKKK K K +KKKKKKKKKKKKKKKKKK K"K#K$K&K'K)K*K,K-K.K/K2K3K4K6K8K9K:K;KM@MAMBMCMDMEMFMHMIMJMLMMMOMPMQMRMSMTMUMVMWMXMZM[M\M]M^M_M`MaMcMdMeMgMiMjMkMlMmMnMoMpMqMrMsMtMuMwMxMyMzM{M|M}M~MMM‚MƒM„M…M†M‡MˆM‰MŠMŒMMŽMMM‘M’M“M”M•M—M˜M™MšM›MœMMžM M¡M¢M£M¤M¥M§M¨M©MªM«M¬M­M®M°M±M²M³M´MµM¶M·M¹MºM»M¼M¾M¿MÀMÁMÂMÃMÄMÅMÆMÇMÉMÊMËMÌMÎMÐMÑMÒMÔMÕMÖM×MØMÙMÚMÛMÜMÝMÞMßMàMáMâMãMäMåMæMçMèMéMêMëMïMðMñMóMôMõMöM÷MøMùMúMýMÿMMMMMMMMM M +M M +MMMMMMMMMMMMMMMM M!M"M#M%M'M(M*M+M,M-M.M0M2M3M5M6M7M8M9M;M<M=M>M?MBMCMDMEMFMGMHMIMJMLMMMNMOMPMQMRMTMUMVMWMXMYMZM[M]M_M`MaMbMcMdMeMfMgMhMiMjMkMlMmMnMoMqMsMtMuMvMwMxMyMzM|M~MM€MM‚M„M…M‡MˆM‰MŠM‹MMM‘M˜M¡M¢M£M¤M¥M§M¨M©MªM«M­M®M¯M°M±M²M´MµM¶M·M¸M¹MºM»M½M¿MÀMÁMÂMÃMÄMÅMÇMÈMÊMËMÍMÎMÏMÐMÑMÒMÓMÔMÕMÖM×MÙMÚMÛMÜMÝMÞMßMãMåMæMçMèMéMêMëMìMïMðMñMòMóMôMõMöM÷MøMùMúMûMüMýMMMMMMMM M +M MMMMMMMMMMMMM M!M"M#M$M%M&M'M(M*M,M-M.M/M0M1M3M4eUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/builtins.pyq"]q#(KKKKKxeUC/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/exceptions.pyq$]q%(KKKKKKK K +K Keuu. \ No newline at end of file Index: chips2/test_suite/real_main.v =================================================================== --- chips2/test_suite/real_main.v (nonexistent) +++ chips2/test_suite/real_main.v (revision 2) @@ -0,0 +1,99 @@ +//name : real_main +//tag : c components +//source_file : test.c +///========= +/// +///*Created by C2CHIP* + +// Register Allocation +// =================== +// Register Name Size +// 0 real_main return address 2 + +`timescale 1ns/1ps +module real_main; + integer file_count; + reg [15:0] timer; + reg [1:0] program_counter; + reg [15:0] address_2; + reg [15:0] data_out_2; + reg [15:0] data_in_2; + reg write_enable_2; + reg [15:0] address_4; + reg [31:0] data_out_4; + reg [31:0] data_in_4; + reg write_enable_4; + reg [15:0] register_0; + reg clk; + reg rst; + + ////////////////////////////////////////////////////////////////////////////// + // CLOCK AND RESET GENERATION + // + // This file was generated in test bench mode. In this mode, the verilog + // output file can be executed directly within a verilog simulator. + // In test bench mode, a simulated clock and reset signal are generated within + // the output file. + // Verilog files generated in testbecnch mode are not suitable for synthesis, + // or for instantiation within a larger design. + + initial + begin + rst <= 1'b1; + #50 rst <= 1'b0; + end + + + initial + begin + clk <= 1'b0; + while (1) begin + #5 clk <= ~clk; + end + end + + + ////////////////////////////////////////////////////////////////////////////// + // FSM IMPLEMENTAION OF C PROCESS + // + // This section of the file contains a Finite State Machine (FSM) implementing + // the C process. In general execution is sequential, but the compiler will + // attempt to execute instructions in parallel if the instruction dependencies + // allow. Further concurrency can be achieved by executing multiple C + // processes concurrently within the device. + + always @(posedge clk) + begin + + //implement timer + timer <= 16'h0000; + + case(program_counter) + + 16'd0: + begin + program_counter <= 16'd1; + program_counter <= 16'd3; + register_0 <= 16'd1; + end + + 16'd1: + begin + program_counter <= 16'd3; + $finish; + program_counter <= program_counter; + end + + 16'd3: + begin + program_counter <= 16'd2; + program_counter <= register_0; + end + + endcase + if (rst == 1'b1) begin + program_counter <= 0; + end + end + +endmodule Index: chips2/test_suite/test_c2verilog =================================================================== --- chips2/test_suite/test_c2verilog (nonexistent) +++ chips2/test_suite/test_c2verilog (revision 2) @@ -0,0 +1,2887 @@ +#!/usr/bin/env python +import os +import sys + +os.system("python-coverage erase") + +def test(test, code, no_init=False): + f = open("test.c", 'w') + f.write(code) + f.close() + if no_init: + result = os.system("python-coverage run -p ../c2verilog iverilog run no_initialize_memory test.c") + else: + result = os.system("python-coverage run -p ../c2verilog iverilog run test.c") + if(os.path.exists("main")): + os.remove("main") + if(os.path.exists("arbiter")): + os.remove("arbiter") + if(os.path.exists("real_main")): + os.remove("real_main") + + if result == 0: + print test, "...pass" + else: + print test, "...fail" + sys.exit(0) + + if no_init: + result = os.system("python-coverage run -p ../c2verilog iverilog run speed no_initialize_memory test.c") + else: + result = os.system("python-coverage run -p ../c2verilog iverilog run speed test.c") + if(os.path.exists("main")): + os.remove("main") + if(os.path.exists("arbiter")): + os.remove("arbiter") + if(os.path.exists("real_main")): + os.remove("real_main") + + if result == 0: + print test, "...pass" + else: + print test, "...fail" + sys.exit(0) + +def test_fails(test, code, no_init=False): + f = open("test.c", 'w') + f.write(code) + f.close() + print "One error expected ..." + if no_init: + result = os.system("python-coverage run -p ../c2verilog iverilog run no_initialize_memory test.c") + else: + result = os.system("python-coverage run -p ../c2verilog iverilog run test.c") + if result == 0: + print test, "...fail" + sys.exit(0) + else: + print test, "...pass" + +test("unsigned divide 1", +""" +void main(){ + unsigned a = 10; + unsigned b = 5; + assert(a/b==2); +} +""" +) + +test("long unsigned divide 1", +""" +void main(){ + long unsigned a = 1000000L; + long unsigned b = 500000L; + assert(a/b==2); +} +""" +) + +test("divide 1", +""" +void main(){ + int a = 10; + int b = 5; + assert(a/b==2); +} +""" +) + +test("long divide 1", +""" +void main(){ + long a = 1000000L; + long b = 500000L; + assert(a/b==2); +} +""" +) + +test("long 1", +""" +void main(){ + long a = 100000L; + assert(a==100000L); +} +""" +) + +test("long 2", +""" +void main(){ + long a = 100000L; + assert(sizeof a == 4); +} +""" +) + +test("long 3", +""" +void main(){ + long a = 0xffffL; + assert(a+1 != 0); + assert(a+1 == 0x10000L); +} +""" +) + +test("long 4", +""" +void main(){ + long a = 0xffffL; + long b = 0xffffL; + assert(a+b == 0x1fffeL); +} +""" +) +test("long 5", +""" +void main(){ + long a = 0xffffffffUL; + long b = 0x0; + assert(a < b); +} +""" +) +test("long 6", +""" +void main(){ + unsigned long a = 0xffffffffUL; + long b = 0x0; + assert(a > b); +} +""" +) + +test("long 7", +""" +void test_long(long a){ + assert(a+1 != 0); + assert(a+1 == 0x10000L); +} + +void main(){ + long a = 0xffffL; + test_long(a); +} +""" +) + +test("long 8", +""" +void test_long(unsigned long a){ + assert(a > 0); +} + +void main(){ + unsigned long a = 0xffffffffUL; + test_long(a); +} +""" +) + +test("long 9", +""" +void test_long(long a){ + assert(a < 0); +} + +void main(){ + unsigned long a = 0xffffffffUL; + test_long(a); +} +""" +) + +test("long 10", +""" +void test_long(unsigned long a){ + assert(a > 0); +} + +void main(){ + long a = 0xffffffffUL; + test_long(a); +} +""" +) + +test("long 11", +""" +void main(){ + long a[2]; + a[0] = 0xffffffffUL; + a[1] = 0xffffffffUL; + assert(a[1] == 0xffffffffUL); +} +""" +) + +test("long 12", +""" +void main(){ + long a[2]; + int b[2]; + a[0] = 1; + b[0] = 2; + a[1] = 3; + b[1] = 4; + assert(a[0] == 1); + assert(b[0] == 2); + assert(a[1] == 3); + assert(b[1] == 4); +} +""" +) + +test("void 1", +""" +void func(unsigned i){ +} +void main(){ + int a = 1; + assert(a++ == 1); + assert(a++ == 2); + assert(a == 3); + assert(a-- == 3); + assert(a-- == 2); + assert(a == 1); +} +""" +) + +test("postfix 1", +""" +int main(){ + int a = 1; + assert(a++ == 1); + assert(a++ == 2); + assert(a == 3); + assert(a-- == 3); + assert(a-- == 2); + assert(a == 1); + return 0; +} +""" +) + + +test("sizeof 1", +""" +int main(){ + unsigned a = 0xffffU; + unsigned b = 0x7fff; + unsigned c[4]; + unsigned d[] = "asdfg"; + assert(sizeof a == 2); + assert(sizeof b == 2); + assert(sizeof c == 8); + assert(sizeof d == 12); + return 0; +} +""" +) + +test("type_unsigned 1", +""" +int main(){ + unsigned a = 0xffffU; + unsigned b = 0x7fff; + assert(a==0xffffU); + assert(a > b); + + return 0; +} +""" +) + +test("type_unsigned 2", +""" +int main(){ + unsigned a = 0xffffU; + unsigned b = 0x7fff; + assert(a==0xffffU); + assert(b < a); + + return 0; +} +""" +) + +test("type_unsigned 3", +""" +int test(unsigned a){ + return a; +} + +int main(){ + assert(test(3) == 3); + return 0; +} +""" +) + +test("type_unsigned 4", +""" +int main(){ + int a = 1; + unsigned b = 1; + assert(a == b); + return 0; +} +""" +) + +test("type_unsigned 5", +""" +int main(){ + int a = 1; + assert(a == 1); + return 0; +} +""" +) +test("type_unsigned 6", +""" +int main(){ + int a = 1; + assert(1 == a); + return 0; +} +""" +) +test("type_unsigned 7", +""" +int main(){ + unsigned b = 1; + assert(1 == b); + return 0; +} +""" +) +test("type_unsigned 8", +""" +int main(){ + unsigned b = 1; + assert(b == 1); + return 0; +} +""" +) + +test("type_compatibility 1", +""" +int main(){ + int a = 4; + char b = 6; + b = a; + assert(b==4); + return 0; +} +""" +) + +test("type_compatibility 2", +""" +int main(){ + int a[2]; + char b[2]; + b = a; + return 0; +} +""" +) + +test("type_compatibility 3", +""" +int main(){ + int a[2]; + char b[2]; + a = b; + return 0; +} +""" +) + +test("type_compatibility 4", +""" +int main(){ + long a[2]; + char b[2]; + a = b; + return 0; +} +""" +) + +test("type_compatibility 5", +""" +int main(){ + long a[2]; + char b[2]; + a = b; + return 0; +} +""" +) + +test("string 1 a", +""" +int main(){ + int c[4] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} + +""") + +test("string 1 b", +""" +int main(){ + int c[4] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} + +""", True) + +test("string 2a", +""" +int main(){ + int c[] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} + +""") + +test("string 2b", +""" +int main(){ + int c[] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} + +""", True) + +test_fails("string 3", +""" +int main(){ + int c[]; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} + +""") + +test("string 4a", +""" +int test(char c[]){ + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + c[0] = 'b'; + c[1] = 'B'; + c[2] = '2'; + c[3] = 0; + return 0; +} +int main(){ + char c[] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + test(c); + assert(c[0] == 'b'); + assert(c[1] == 'B'); + assert(c[2] == '2'); + assert(c[3] == 0); + return 0; +} + +""") + +test("string 4b", +""" +int test(char c[]){ + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + c[0] = 'b'; + c[1] = 'B'; + c[2] = '2'; + c[3] = 0; + return 0; +} +int main(){ + char c[] = "aA1"; + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + test(c); + assert(c[0] == 'b'); + assert(c[1] == 'B'); + assert(c[2] == '2'); + assert(c[3] == 0); + return 0; +} + +""", True) + +test_fails("string 5", +""" +int main(){ + int c[] "\\n"; + assert(c[0] == 10); + assert(c[1] == 0); + return 0; +} + +""") + +test("string 6a", +""" +int test(char c[]){ + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} +int main(){ + test("aA1"); + return 0; +} +""") + +test("string 6b", +""" +int test(char c[]){ + assert(c[0] == 97); + assert(c[1] == 65); + assert(c[2] == 49); + assert(c[3] == 0); + return 0; +} +int main(){ + test("aA1"); + return 0; +} +""", True) + +test("string 7a", +""" +int main(){ + char c[] = "a\\n"; + assert(c[0] == 97); + assert(c[1] == 10); + assert(c[2] == 0); + return 0; +} +""") + +test("string 7b", +""" +int main(){ + char c[] = "a\\n"; + assert(c[0] == 97); + assert(c[1] == 10); + assert(c[2] == 0); + return 0; +} +""", True) + +test("char 1", +""" +int main(){ + int c = 'a'; + assert(c == 97); + return 0; +} + +""") +test("char 2", +""" +int main(){ + int c = 'A'; + assert(c == 65); + return 0; +} + +""") +test("char 3", +""" +int main(){ + int c = '1'; + assert(c == 49); + return 0; +} + +""") +test("char 4", +""" +int main(){ + int c = '\\n'; + assert(c == 10); + return 0; +} + +""") + +test("unsigned long modulo 1", +""" +unsigned long int main(){ + unsigned long int a = 3; + unsigned long int b = 4; + assert(a%b == 3); + return 0; +} + +""") + +test("unsigned long modulo 3", +""" +unsigned long int main(){ + unsigned long int a = 7; + unsigned long int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("unsigned long modulo 4", +""" +unsigned long int main(){ + unsigned long int a = 15; + unsigned long int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("unsigned long modulo 9", +""" +unsigned long int main(){ + unsigned long int a = 32766; + unsigned long int b = 0; + assert(a%b == 32766); + return 0; +} + +""") + +test("unsigned long division 1", +""" +unsigned long int main(){ + unsigned long int a = 15; + unsigned long int b = 3; + assert(a/b == 5); + return 0; +} + +""") + + +test("unsigned long division 2", +""" +unsigned long int main(){ + unsigned long int a = 12; + unsigned long int b = 4; + assert(a/b == 3); + return 0; +} + +""") + +test("unsigned long division 3", +""" +unsigned long int main(){ + unsigned long int a = 1; + unsigned long int b = 1; + assert(a/b == 1); + return 0; +} + +""") + +test("unsigned long division 6", +""" +unsigned long int main(){ + unsigned long int a = 0; + unsigned long int b = 1; + assert(a/b == 0); + return 0; +} + +""") + +test("unsigned long division 7", +""" +unsigned long int main(){ + unsigned long int a = 5; + unsigned long int b = 2; + assert(a/b == 2); + return 0; +} + +""") + +test("unsigned long division 9", +""" +unsigned long int main(){ + unsigned long int a = 0; + unsigned long int b = 32767; + assert(a/b == 0); + return 0; +} + +""") + +test("unsigned long division 10", +""" +unsigned long int main(){ + unsigned long int a = 32767; + unsigned long int b = 1; + assert(a/b == 32767); + return 0; +} + +""") + +test("unsigned long division 11", +""" +unsigned long int main(){ + unsigned long int a = 32767; + unsigned long int b = 2; + assert(a/b == 16383); + return 0; +} + +""") + +test("unsigned long division 12", +""" +unsigned long int main(){ + unsigned long int a = 32767; + unsigned long int b = 32767; + assert(a/b == 1); + return 0; +} + +""") + +test("unsigned modulo 1", +""" +unsigned int main(){ + unsigned int a = 3; + unsigned int b = 4; + assert(a%b == 3); + return 0; +} + +""") + +test("unsigned modulo 3", +""" +unsigned int main(){ + unsigned int a = 7; + unsigned int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("unsigned modulo 4", +""" +unsigned int main(){ + unsigned int a = 15; + unsigned int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("unsigned modulo 9", +""" +unsigned int main(){ + unsigned int a = 32766; + unsigned int b = 0; + assert(a%b == 32766); + return 0; +} + +""") + +test("unsigned division 1", +""" +unsigned int main(){ + unsigned int a = 15; + unsigned int b = 3; + assert(a/b == 5); + return 0; +} + +""") + + +test("unsigned division 2", +""" +unsigned int main(){ + unsigned int a = 12; + unsigned int b = 4; + assert(a/b == 3); + return 0; +} + +""") + +test("unsigned division 3", +""" +unsigned int main(){ + unsigned int a = 1; + unsigned int b = 1; + assert(a/b == 1); + return 0; +} + +""") + +test("unsigned division 6", +""" +unsigned int main(){ + unsigned int a = 0; + unsigned int b = 1; + assert(a/b == 0); + return 0; +} + +""") + +test("unsigned division 7", +""" +unsigned int main(){ + unsigned int a = 5; + unsigned int b = 2; + assert(a/b == 2); + return 0; +} + +""") + +test("unsigned division 9", +""" +unsigned int main(){ + unsigned int a = 0; + unsigned int b = 32767; + assert(a/b == 0); + return 0; +} + +""") + +test("unsigned division 10", +""" +unsigned int main(){ + unsigned int a = 32767; + unsigned int b = 1; + assert(a/b == 32767); + return 0; +} + +""") + +test("unsigned division 11", +""" +unsigned int main(){ + unsigned int a = 32767; + unsigned int b = 2; + assert(a/b == 16383); + return 0; +} + +""") + +test("unsigned division 12", +""" +unsigned int main(){ + unsigned int a = 32767; + unsigned int b = 32767; + assert(a/b == 1); + return 0; +} + +""") + +test("long modulo 1", +""" +long int main(){ + long int a = 3; + long int b = 4; + assert(a%b == 3); + return 0; +} + +""") + +test("long modulo 2", +""" +long int main(){ + long int a = -3; + long int b = 4; + assert(a%b == -3); + return 0; +} + +""") + +test("long modulo 3", +""" +long int main(){ + long int a = 7; + long int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("long modulo 4", +""" +long int main(){ + long int a = 15; + long int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("long modulo 5", +""" +long int main(){ + long int a = -7; + long int b = 8; + assert(a%b == -7); + return 0; +} + +""") + +test("long modulo 6", +""" +long int main(){ + long int a = -15; + long int b = 8; + assert(a%b == -7); + return 0; +} + +""") + +test("long modulo 7", +""" +long int main(){ + long int a = 7; + long int b = -8; + assert(a%b == 7); + return 0; +} + +""") + +test("long modulo 8", +""" +long int main(){ + long int a = 15; + long int b = -8; + assert(a%b == 7); + return 0; +} + +""") + +test("long modulo 9", +""" +long int main(){ + long int a = 32766; + long int b = 0; + assert(a%b == 32766); + return 0; +} + +""") + +test("long division 1", +""" +long int main(){ + long int a = 15; + long int b = 3; + assert(a/b == 5); + return 0; +} + +""") + + +test("long division 2", +""" +long int main(){ + long int a = 12; + long int b = 4; + assert(a/b == 3); + return 0; +} + +""") + +test("long division 3", +""" +long int main(){ + long int a = 1; + long int b = 1; + assert(a/b == 1); + return 0; +} + +""") + +test("long division 4", +""" +long int main(){ + long int a = 1; + long int b = -1; + assert(a/b == -1); + return 0; +} + +""") + +test("long division 5", +""" +long int main(){ + long int a = -1; + long int b = 1; + assert(a/b == -1); + return 0; +} + +""") + +test("long division 6", +""" +long int main(){ + long int a = 0; + long int b = 1; + assert(a/b == 0); + return 0; +} + +""") + +test("long division 7", +""" +long int main(){ + long int a = 5; + long int b = 2; + assert(a/b == 2); + return 0; +} + +""") + +test("long division 8", +""" +long int main(){ + long int a = -5; + long int b = 2; + assert(a/b == -2); + return 0; +} + +""") + +test("long division 9", +""" +long int main(){ + long int a = 0; + long int b = 32767; + assert(a/b == 0); + return 0; +} + +""") + +test("long division 10", +""" +long int main(){ + long int a = 32767; + long int b = 1; + assert(a/b == 32767); + return 0; +} + +""") + +test("long division 11", +""" +long int main(){ + long int a = 32767; + long int b = 2; + assert(a/b == 16383); + return 0; +} + +""") + +test("long division 12", +""" +long int main(){ + long int a = 32767; + long int b = 32767; + assert(a/b == 1); + return 0; +} + +""") + +test("long division 13", +""" +long int main(){ + long int a = -32767-1; + long int b = -32767-1; + assert(a/b == 1); + return 0; +} + +""") + +test("long division 14", +""" +long int main(){ + long int a = -32767; + long int b = -1; + assert(a/b == 32767); + return 0; +} + +""") + +test("modulo 1", +""" +int main(){ + int a = 3; + int b = 4; + assert(a%b == 3); + return 0; +} + +""") + +test("modulo 2", +""" +int main(){ + int a = -3; + int b = 4; + assert(a%b == -3); + return 0; +} + +""") + +test("modulo 3", +""" +int main(){ + int a = 7; + int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("modulo 4", +""" +int main(){ + int a = 15; + int b = 8; + assert(a%b == 7); + return 0; +} + +""") + +test("modulo 5", +""" +int main(){ + int a = -7; + int b = 8; + assert(a%b == -7); + return 0; +} + +""") + +test("modulo 6", +""" +int main(){ + int a = -15; + int b = 8; + assert(a%b == -7); + return 0; +} + +""") + +test("modulo 7", +""" +int main(){ + int a = 7; + int b = -8; + assert(a%b == 7); + return 0; +} + +""") + +test("modulo 8", +""" +int main(){ + int a = 15; + int b = -8; + assert(a%b == 7); + return 0; +} + +""") + +test("modulo 9", +""" +int main(){ + int a = 32766; + int b = 0; + assert(a%b == 32766); + return 0; +} + +""") + +test("division 1", +""" +int main(){ + int a = 15; + int b = 3; + assert(a/b == 5); + return 0; +} + +""") + + +test("division 2", +""" +int main(){ + int a = 12; + int b = 4; + assert(a/b == 3); + return 0; +} + +""") + +test("division 3", +""" +int main(){ + int a = 1; + int b = 1; + assert(a/b == 1); + return 0; +} + +""") + +test("division 4", +""" +int main(){ + int a = 1; + int b = -1; + assert(a/b == -1); + return 0; +} + +""") + +test("division 5", +""" +int main(){ + int a = -1; + int b = 1; + assert(a/b == -1); + return 0; +} + +""") + +test("division 6", +""" +int main(){ + int a = 0; + int b = 1; + assert(a/b == 0); + return 0; +} + +""") + +test("division 7", +""" +int main(){ + int a = 5; + int b = 2; + assert(a/b == 2); + return 0; +} + +""") + +test("division 8", +""" +int main(){ + int a = -5; + int b = 2; + assert(a/b == -2); + return 0; +} + +""") + +test("division 9", +""" +int main(){ + int a = 0; + int b = 32767; + assert(a/b == 0); + return 0; +} + +""") + +test("division 10", +""" +int main(){ + int a = 32767; + int b = 1; + assert(a/b == 32767); + return 0; +} + +""") + +test("division 11", +""" +int main(){ + int a = 32767; + int b = 2; + assert(a/b == 16383); + return 0; +} + +""") + +test("division 12", +""" +int main(){ + int a = 32767; + int b = 32767; + assert(a/b == 1); + return 0; +} + +""") + +test("division 13", +""" +int main(){ + int a = -32767-1; + int b = -32767-1; + assert(a/b == 1); + return 0; +} + +""") + +test("division 14", +""" +int main(){ + int a = -32767; + int b = -1; + assert(a/b == 32767); + return 0; +} + +""") + +test("struct with array 1", +""" +typedef struct {int a; int b; int c[2];} blah; +blah myblah; + +void test(){ + assert(myblah.a == 1); + assert(myblah.b == 2); + assert(myblah.c[0] == 3); + assert(myblah.c[1] == 4); + myblah.a = 5; + myblah.b = 6; + myblah.c[0] = 7; + myblah.c[1] = 8; +} + +void main(){ + myblah.a = 1; + myblah.b = 2; + myblah.c[0] = 3; + myblah.c[1] = 4; + test(); + assert(myblah.a == 5); + assert(myblah.b == 6); + assert(myblah.c[0] == 7); + assert(myblah.c[1] == 8); +} +""" +) + +test("global variables 1", +""" +int a; + +void test(){ + assert(a==12); + a = 24; +} + +void main(){ + a = 12; + test(); + assert(a==24); +} + +""" +) + +test("global variables 2", +""" +int a[10]; + +void test(){ + assert(a[0] == 0); + assert(a[1] == 1); + assert(a[2] == 2); + assert(a[3] == 3); + a[0] = 4; + a[1] = 5; + a[2] = 6; + a[3] = 7; +} + +void main(){ + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + test(); + assert(a[0] == 4); + assert(a[1] == 5); + assert(a[2] == 6); + assert(a[3] == 7); +} + +""" +) + +test("global variables 3", +""" +int a=0, b=1, c=2; + +void test(){ + assert(a == 3); + assert(b == 4); + assert(c == 5); + a=6; + b=7; + c=8; +} + +void main(){ + assert(a == 0); + assert(b == 1); + assert(c == 2); + a=3; + b=4; + c=5; + test(); + assert(a == 6); + assert(b == 7); + assert(c == 8); +} + +""" +) + +test("global variables 4", +""" +typedef struct {int a; int b; int c;} blah; +blah myblah; + +void test(){ + assert(myblah.a == 1); + assert(myblah.b == 2); + assert(myblah.c == 3); + myblah.a = 4; + myblah.b = 5; + myblah.c = 6; +} + +void main(){ + myblah.a = 1; + myblah.b = 2; + myblah.c = 3; + test(); + assert(myblah.a == 4); + assert(myblah.b == 5); + assert(myblah.c == 6); +} +""" +) + +test("void functions 1", +""" +void main(){ + int a; + int b; + b = a; +} + +""" +) + +test("void functions 2", +""" +void test(){ + return; +} + +void main(){ + test(); +} + +""" +) + +test_fails("void functions 3", +""" +void test(){ + return; +} + +void main(){ + int a; + a = test(); +} + +""" +) + +test_fails("void functions 4", +""" +void test(){ + return 10; +} + +void main(){ + int a; + a = test(); +} + +""" +) + +test_fails("type_checking 1", +""" +int main(){ + int a[4]; + int b; + b = a; + return 0; +} + +""" +) + +test_fails("type_checking 2", +""" +int main(){ + int a[4]; + int b[4]; + b[a]=12; + return 0; +} + +""" +) + +test_fails("type_checking 3", +""" +int main(){ + int a[4]; + int b; + if(a) b=12; + return 0; +} + +""" +) + +test_fails("type_checking 4", +""" +int main(){ + int a[4]; + int b; + while(a) b=12; + return 0; +} + +""" +) + +test_fails("type_checking 5", +""" +int main(){ + int a[4]; + int b; + for(;a;) b=12; + return 0; +} + +""" +) + +test_fails("type_checking 6", +""" +int main(){ + int a[4]; + int b; + switch(a){} + return 0; +} + +""" +) + +test_fails("type_checking 7", +""" +int main(){ + int a[4]; + int b; + switch(b){case a:b=12;} + return 0; +} + +""" +) + +test_fails("type_checking 8", +""" +int test(int a[]){ + return 0; +} + +int main(){ + int b; + test(b); + return 0; +} + +""" +) + +test_fails("type_checking 9", +""" +int test(int a){ + return 0; +} + +int main(){ + int b[4]; + test(b); + return 0; +} + +""" +) + +test("array passing 1", +""" + +int test(int a[]){ + assert(a[0] == 0); + assert(a[1] == 1); + assert(a[2] == 2); + assert(a[3] == 3); + a[0] = 4; + a[1] = 5; + a[2] = 6; + a[3] = 7; + return 0; +} + +int main(){ + int a[4]; + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + test(a); + assert(a[0] == 4); + assert(a[1] == 5); + assert(a[2] == 6); + assert(a[3] == 7); + return 0; +} + +""" +) + +test("array passing 2", +""" + +int test(int a[]){ + assert(a[0] == 0); + assert(a[1] == 1); + assert(a[2] == 2); + assert(a[3] == 3); + a[0] = 4; + a[1] = 5; + a[2] = 6; + a[3] = 7; + return 0; +} + +int main(){ + int a[4]; + int b[4]; + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + b = a; + test(b); + assert(a[0] == 4); + assert(a[1] == 5); + assert(a[2] == 6); + assert(a[3] == 7); + return 0; +}""" +) + +test("struct 1", +""" +struct blah {int a; int b; int c;}; +int main(){ + struct blah myblah; + myblah.a = 1; + myblah.b = 2; + myblah.c = 3; + assert(myblah.a == 1); + assert(myblah.b == 2); + assert(myblah.c == 3); + return 0; +} +""" +) +test("struct 2", +""" +struct as {int a; int b; int c;}; +int main(){ + struct as asa; + struct as asb; + asa.a = 1; + asb.a = 3; + asa.b = 2; + asb.b = 2; + asa.c = 3; + asb.c = 1; + assert(asa.a == 1); + assert(asb.a == 3); + assert(asa.b == 2); + assert(asb.b == 2); + assert(asa.c == 3); + assert(asb.c == 1); + return 0; +} +""" +) +test("struct 3", +""" +typedef struct {int a; int b; int c;} blah; +int main(){ + blah myblah; + myblah.a = 1; + myblah.b = 2; + myblah.c = 3; + assert(myblah.a == 1); + assert(myblah.b == 2); + assert(myblah.c == 3); + return 0; +} +""" +) +test("struct 4", +""" +typedef struct{int a; int b; int c;} mytype; +typedef struct{mytype a;} othertype; +int main(){ + othertype a; + othertype b; + a.a.a = 1; + b.a.a = 2; + a.a.b = 3; + b.a.b = 4; + a.a.c = 5; + b.a.c = 6; + assert(a.a.a == 1); + assert(b.a.a == 2); + assert(a.a.b == 3); + assert(b.a.b == 4); + assert(a.a.c == 5); + assert(b.a.c == 6); + return 0; +} +""" +) +test("include 1", +"""#include "test_include.c" +int main(){ + assert(include_function()==12); + return 0; +} +""" +) +test("switch 1", + """int main(){ + switch(0){ + case 0: return 3; + case 1: return 2; + case 2: return 1; + default: return 0; + } + } + """ +) +test("switch 2", + """int main(){ + switch(2){ + case 0: return 3; + case 1: return 2; + case 2: return 1; + default: return 0; + } + } + """ +) +test("switch 3", + """int main(){ + switch(5){ + case 0: return 3; + case 1: return 2; + case 2: return 1; + default: return 0; + } + } + """ +) +test("switch 4", + """int main(){ + int a = 0; + switch(0){ + case 0: a = 1; + case 1: a = 2; + case 2: a = 3; + default: a = 4; + } + return a; + } + """ +) +test("switch 5", + """int main(){ + int a = 0; + switch(1){ + case 0: a = 1; + case 1: a = 2; + case 2: a = 3; + default: a = 4; + } + return a; + } + """ +) +test("switch 6", + """int main(){ + int a = 1; + switch(10){ + case 0: a = 1; + case 1: a = 2; + case 2: a = 3; + default: a = 4; + } + return a; + } + """ +) +test("switch 7", + """int main(){ + int a = 1; + switch(0){ + case 0: a = 1; break; + case 1: a = 2; break; + case 2: a = 3; break; + default: a = 4; break; + } + return a; + } + """ +) +test("switch 8", + """int main(){ + int a = 1; + switch(2){ + case 0: a = 1; break; + case 1: a = 2; break; + case 2: a = 3; break; + default: a = 4; break; + } + return a; + } + """ +) +test("switch 9", +"""int main(){ +int a = 1; +switch(9){ + case 0: a = 1; break; + case 1: a = 2; break; + case 2: a = 3; break; + default: a = 4; break; +} +return a; +} +""" +) + +test("break 0", +""" +int main(){ + int a; + while(1){ + break; + assert(0); + } + return 0; +} +""") +test("break 1", +""" +int main(){ + int a; + for(a=0; a<20; a++){ + if(a == 10){ + break; + } + } + assert(a == 10); + return 0; +} +""") +test("continue 0", +""" +int main(){ + int a; + for(a=1; a<=10; a++){ + if(a <= 5){ + continue; + } + assert(a > 5); + } + return 0; +} +""") +test("ternary 0", +""" +int main(){ + int a; + int b=2; + int c=3; + assert((1?2:3) == 2); + assert((0?2:3) == 3); + a = 1; + assert((a?b:c) == 2); + a = 0; + assert((a?b:c) == 3); + assert((1?b:c) == 2); + assert((0?b:c) == 3); + return 0; +} +""") +test("inplace 0", +""" +int main(){ + int a = 1; + a += 1; + assert(a == 2); + a -= 1; + assert(a == 1); + a *= 2; + assert(a == 2); + a /= 2; + assert(a == 1); + a |= 2; + assert(a == 3); + a &= 2; + assert(a == 2); + a <<= 1; + assert(a == 4); + a >>= 1; + assert(a == 2); + return 0; +} +""") +test("inplace 1", +""" +int main(){ + int a[100]; + a[0] = 1; + a[20] = 1; + a[20] += 1; + assert(a[20] == 2); + a[20] -= 1; + assert(a[20] == 1); + a[20] *= 2; + assert(a[20] == 2); + a[20] /= 2; + assert(a[20] == 1); + a[20] |= 2; + assert(a[20] == 3); + a[20] &= 2; + assert(a[20] == 2); + a[20] <<= 1; + assert(a[20] == 4); + a[20] >>= 1; + assert(a[20] == 2); + assert(a[0] == 1); + return 0; +} +""") +test("increment", +""" +int main(){ + int a = 1; + a++; + assert(a == 2); + a--; + assert(a == 1); + return 0; +} + +""") + +test("assert 0", +"""int main(){ + assert(1); + return 0; +} +""") +test_fails("assert 1", +"""int main(){ + assert(0); + return 0; +} +""") +test("assign", +"""int main(){ + int a; + int b; + int c; + a = 10; + b = 20; + c = a + b; + assert(a == 10); + assert(b == 20); + assert(c == 30); + return 0; +} +""") +test("while", +"""int main(){ + int a = 10; + int b = 0; + while(a){ + a = a - 1; + b = b + 1; + } + assert(b == 10); + return 0; +} +""") +test("while 1", +"""int main(){ + int a = 0; + while(1){ + a = a + 1; + if(a == 10){ + return 0; + } + } +} +""") +test("while 2", +"""int main(){ + while(0){ + assert(0); + } + return 0; +} +""") +test("if", +"""int main(){ + int a = 0; + int b = 0; + if(a){ + b = 10; + assert(0); + } else { + b = 20; + } + assert(b == 20); + return 0; +} +""") +test("if 1", +"""int main(){ + int a = 1; + int b = 0; + if(a){ + b = 10; + } else { + b = 20; + assert(0); + } + assert(b == 10); + return 0; +} +""") +test("if 2", +"""int main(){ + int b = 0; + if(0){ + b = 10; + assert(0); + } else { + b = 20; + } + assert(b == 20); + return 0; +} +""") +test("if 3", +"""int main(){ + int b = 0; + if(1){ + b = 10; + } else { + b = 20; + assert(0); + } + assert(b == 10); + return 0; +} +""") +test("if 4", +"""int main(){ + int b = 0; + if(0){ + b = 10; + assert(0); + } + assert(b == 0); + return 0; +} +""") +test("for 0", +"""int main(){ + int a = 0; + int b; + int c = 1; + for(a=0; a<10; a++){ + b = b + 1; + c = c + 1; + } + assert(b == 10); + assert(c == 11); + return 0; +} +""") +test("for 1", +"""int main(){ + int a = 0; + int b; + int c = 1; + for(; a<10; a++){ + b = b + 1; + c = c + 1; + } + assert(b == 10); + assert(c == 11); + return 0; +} +""") +test("for 2", +"""int main(){ + int a = 0; + int b; + int c = 1; + for(;a<10;){ + b = b + 1; + c = c + 1; + a++; + } + assert(b == 10); + assert(c == 11); + return 0; +} +""") +test("for 3", +"""int main(){ + int a = 0; + int b; + int c = 1; + for(;;){ + if(a>=10) break; + b = b + 1; + c = c + 1; + a++; + } + assert(b == 10); + assert(c == 11); + return 0; +} +""") +test("number 0", +"""int main(){ + return 1; +} +""") +test("report 0", +"""int main(){ + int a = 0; + int b = 1; + int c = 2; + report(a); + report(b); + report(c); + return 0; +} +""") +test("declare 0", +"""int main(){ + int a = 10; + int b = 20, c = 30; + int d[100], e[200]; + assert(a==10); + assert(b==20); + assert(c==30); + return 0; +} +""") +test("wait_clocks 0", +"""int main(){ + int a = 10; + wait_clocks(a); + wait_clocks(10); + return 0; +} +""") +test("function", +""" + +int func(int a){ + return a + 10; +} + +int main(){ + int a = func(10); + assert(a == 20); + return 0; +} + +""") +test("function 1", +""" + +int func(int a){ + assert(a == 20); + return 0; +} + +int main(){ + func(20); + return 0; +} + +""") + +test("function 2", +""" + +int func(int a, int b, int c){ + return a; +} + +int main(){ + assert(func(1, 2, 3) == 1); + return 0; +} + +""") + +test("function 3", +""" + +int func(int a, int b, int c){ + return b; +} + +int main(){ + assert(func(1, 2, 3) == 2); + return 0; +} + +""") + +test("function 4", +""" + +int func(int a, int b, int c){ + return c; +} + +int main(){ + assert(func(1, 2, 3) == 3); + return 0; +} + +""") + +test("function 5", +""" + +int another(int a){ + return a + 1; +} + +int func(int a){ + return another(a) + 1; +} + +int main(){ + assert(func(0) == 2); + return 0; +} + +""") + +test_fails("function 6", +""" + +int func(int a, int b){ + return b; +} + +int main(){ + assert(func(1, 2, 3) == 3); + return 0; +} + +""") +test("expression 1", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a + b + c == 6); + return 0; +} + +""") +test("expression 2", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a - b - c == -4); + return 0; +} + +""") +test("expression 3", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a - (b - c) == 2); + return 0; +} + +""") +test("expression 4", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a * b * c == 6); + return 0; +} + +""") +test("expression 5", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a/b/c == 0); + return 0; +} + +""") +test("expression 6", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(a%b%c == 1); + return 0; +} + +""") +test("expression 7", +""" +int main(){ + int a = 1; + int b = 2; + int c = 3; + assert(-a - (b - c) == 0); + return 0; +} + +""") +test("expression 8", +""" +int fail(){ + assert(0); + return 0; +} +int main(){ + int a = 0 && fail(); + return 0; +} + +""") +test("expression 9", +""" +int fail(){ + assert(0); + return 0; +} +int main(){ + int a = 1 || fail(); + return 0; +} + +""") +test("expression 10", +""" +int main(){ + int a = 1; + assert(a << 2 == 4); + return 0; +} + +""") +test("expression 11", +""" +int main(){ + int a = 1; + int b = 2; + assert(a << b == 4); + return 0; +} + +""") +test("expression 12", +""" +int main(){ + int a = 4; + assert(a >> 2 == 1); + return 0; +} + +""") +test("expression 13", +""" +int main(){ + int a = 4; + int b = 2; + assert(a >> b == 1); + return 0; +} + +""") +test("expression 14", +""" +int main(){ + int a = -1; + assert(~a == 0); + return 0; +} + +""") +test("expression 15", +""" +int main(){ + int a = 1; + assert(!a == 0); + int a = 0; + assert(!a == 1); + return 0; +} + +""") +test("expression 16", +""" +int main(){ + int a = 0xA; + int b = 0x5; + assert((a | b) == 0xF); + assert((a ^ b) == 0xf); + assert((a & b) == 0); + return 0; +} + +""") +test("expression 17", +""" +int fail(){ + assert(0); + return 0; +} +int main(){ + int b = 0; + int a = b && fail(); + return 0; +} + +""") +test("expression 18", +""" +int fail(){ + assert(0); + return 0; +} +int main(){ + assert(~1); + return 0; +} + +""") +test("expression 19", +""" +int main(){ + assert(-1 < 1); + assert(-1 < 0); + assert(0 <= 0); + assert(0 >= 0); + assert(1 >= 0); + assert(1 >= -1); + assert(1 > -1); + assert(1 > 0); + assert(12 != 13); + assert(100 == 100); + return 0; +} + +""") +test("expression 20", +""" +int main(){ + int a = -1; + assert(a >> 2 == -1); + return 0; +} + +""") +test("comment 0", +""" +int main(){ + //assert(0); + //assert(0); + //assert(0); + return 0; +} + +""") +test("comment 1", +""" +int main(){ + /*assert(0); + assert(0); + assert(0);*/ + return 0; +} + +""") +test("array 0", +""" +int main(){ + int a [1024]; + int b [1024]; + a[0] = 1; + a[1] = 2; + a[3] = 3; + assert(a[0] == 1); + assert(a[1] == 2); + assert(a[3] == 3); + return 0; +} + +""") + +test("array 1", +""" +int main(){ + int a [1024]; + int b [1024]; + a[0] = 10; + b[0] = 20; + a[1] = 30; + b[1] = 40; + a[3] = 50; + b[3] = 60; + assert(a[0] == 10); + assert(b[0] == 20); + assert(a[1] == 30); + assert(b[1] == 40); + assert(a[3] == 50); + assert(b[3] == 60); + return 0; +} + +""") + +test_fails("error 0", +""" +int main(){ + int a; + a = c; + return 0; +} + +""") + +test_fails("error 1", +""" +int main(){ + int a; +} + +""") + +test_fails("error 2", +""" +int main(){ + int a blah; +} + +""") + +test_fails("error 3", +""" +int main(){ + int a; + b = a; +} + +""") + +test_fails("error 4", +""" +int main(){ + int a; + a = c(); +} + +""") + +test_fails("error 5", +""" +int main(){ + int a; + a==; +} + +""") +test_fails("error 6", +""" +int main(){ + int a; + a=00x; +} + +""") +test_fails("error 7", +""" +int main(){ + switch(1){ + case 0: + default: + default: + } + return 0; +} +""") +test_fails("error 8", +""" +int main(){ + default: + return 0; +} +""") +test_fails("error 9", +""" +int main(){ + case 1: + return 0; +} +""") +test_fails("error 10", +""" +int main(){ + int a = 12; + switch(a){ + case a + 1: + a++; + } + return 0; +} +""") +test_fails("error 11", +""" +int myfunction(){ + return 0; +} +int main(){ + int a = 12; + myfunction()=10; + return 0; +} +""") +test("input 1", +""" +int main(){ + int b; + b = input_a(); + return 0; +} + +""") + +test("output 1", +""" +int main(){ + output_a(12); + return 0; +} + +""") + +test("input output 1", +""" +int main(){ + if (input_select()){ + output_z(input_a()); + } else { + output_z(input_b()); + } + return 0; +} + +""") + +test("input output 2", +""" +int arbiter(){ + while(1){ + if(ready_a()) output_z(input_a()); + if(ready_b()) output_z(input_b()); + } + return 0; +} + +""") + +test("main not main", +""" +int main(){ + assert(0); + return 0; +} + +//last function is always main +int real_main(){ + return 0; +} +""") + +os.system("python-coverage run -p c2verilog.py") +os.system("python-coverage combine") +os.system("python-coverage report") +os.system("python-coverage annotate c2verilog.py") +os.system("python-coverage annotate compiler/parser.py")
chips2/test_suite/test_c2verilog Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2/test_suite/consumer.c =================================================================== --- chips2/test_suite/consumer.c (nonexistent) +++ chips2/test_suite/consumer.c (revision 2) @@ -0,0 +1,13 @@ +void consumer(){ + assert(input_a()==1); + assert(input_a()==2); + assert(input_a()==3); + assert(input_a()==4); + assert(input_a()==5); + assert(input_a()==6); + assert(input_a()==7); + assert(input_a()==8); + assert(input_a()==9); + assert(input_a()==10); + report(1); +} Index: chips2/test_suite/arbiter.v =================================================================== --- chips2/test_suite/arbiter.v (nonexistent) +++ chips2/test_suite/arbiter.v (revision 2) @@ -0,0 +1,191 @@ +//name : arbiter +//tag : c components +//input : input_a:16 +//input : input_b:16 +//output : output_z:16 +//source_file : test.c +///======= +/// +///*Created by C2CHIP* + +// Register Allocation +// =================== +// Register Name Size +// 0 arbiter return address 2 +// 1 temporary_register 2 + +`timescale 1ns/1ps +module arbiter(input_a,input_b,input_a_stb,input_b_stb,output_z_ack,clk,rst,output_z,output_z_stb,input_a_ack,input_b_ack); + integer file_count; + input [15:0] input_a; + input [15:0] input_b; + input input_a_stb; + input input_b_stb; + input output_z_ack; + input clk; + input rst; + output [15:0] output_z; + output output_z_stb; + output input_a_ack; + output input_b_ack; + reg [15:0] timer; + reg [3:0] program_counter; + reg [15:0] address_2; + reg [15:0] data_out_2; + reg [15:0] data_in_2; + reg write_enable_2; + reg [15:0] address_4; + reg [31:0] data_out_4; + reg [31:0] data_in_4; + reg write_enable_4; + reg [15:0] register_0; + reg [15:0] register_1; + reg [15:0] s_output_z_stb; + reg [15:0] s_output_z; + reg [15:0] s_input_a_ack; + reg [15:0] s_input_b_ack; + + ////////////////////////////////////////////////////////////////////////////// + // FSM IMPLEMENTAION OF C PROCESS + // + // This section of the file contains a Finite State Machine (FSM) implementing + // the C process. In general execution is sequential, but the compiler will + // attempt to execute instructions in parallel if the instruction dependencies + // allow. Further concurrency can be achieved by executing multiple C + // processes concurrently within the device. + + always @(posedge clk) + begin + + //implement timer + timer <= 16'h0000; + + case(program_counter) + + 16'd0: + begin + program_counter <= 16'd1; + program_counter <= 16'd3; + register_0 <= 16'd1; + end + + 16'd1: + begin + program_counter <= 16'd3; + program_counter <= program_counter; + end + + 16'd3: + begin + program_counter <= 16'd2; + register_1 <= 0; + register_1[0] <= input_a_stb; + end + + 16'd2: + begin + program_counter <= 16'd6; + if (register_1 == 0) + program_counter <= 4; + end + + 16'd6: + begin + program_counter <= 16'd7; + register_1 <= input_a; + program_counter <= 6; + s_input_a_ack <= 1'b1; + if (s_input_a_ack == 1'b1 && input_a_stb == 1'b1) begin + s_input_a_ack <= 1'b0; + program_counter <= 16'd7; + end + end + + 16'd7: + begin + program_counter <= 16'd5; + s_output_z <= register_1; + program_counter <= 7; + s_output_z_stb <= 1'b1; + if (s_output_z_stb == 1'b1 && output_z_ack == 1'b1) begin + s_output_z_stb <= 1'b0; + program_counter <= 5; + end + end + + 16'd5: + begin + program_counter <= 16'd4; + program_counter <= 16'd4; + end + + 16'd4: + begin + program_counter <= 16'd12; + register_1 <= 0; + register_1[0] <= input_b_stb; + end + + 16'd12: + begin + program_counter <= 16'd13; + if (register_1 == 0) + program_counter <= 10; + end + + 16'd13: + begin + program_counter <= 16'd15; + register_1 <= input_b; + program_counter <= 13; + s_input_b_ack <= 1'b1; + if (s_input_b_ack == 1'b1 && input_b_stb == 1'b1) begin + s_input_b_ack <= 1'b0; + program_counter <= 16'd15; + end + end + + 16'd15: + begin + program_counter <= 16'd14; + s_output_z <= register_1; + program_counter <= 15; + s_output_z_stb <= 1'b1; + if (s_output_z_stb == 1'b1 && output_z_ack == 1'b1) begin + s_output_z_stb <= 1'b0; + program_counter <= 14; + end + end + + 16'd14: + begin + program_counter <= 16'd10; + program_counter <= 16'd10; + end + + 16'd10: + begin + program_counter <= 16'd11; + program_counter <= 16'd3; + end + + 16'd11: + begin + program_counter <= 16'd9; + program_counter <= register_0; + end + + endcase + if (rst == 1'b1) begin + program_counter <= 0; + s_input_a_ack <= 0; + s_input_b_ack <= 0; + s_output_z_stb <= 0; + end + end + assign input_a_ack = s_input_a_ack; + assign input_b_ack = s_input_b_ack; + assign output_z_stb = s_output_z_stb; + assign output_z = s_output_z; + +endmodule Index: chips2/c2verilog =================================================================== --- chips2/c2verilog (nonexistent) +++ chips2/c2verilog (revision 2) @@ -0,0 +1,49 @@ +#!/usr/bin/env python +"""A C to Verilog compiler - Command line interface""" + +__author__ = "Jon Dawson" +__copyright__ = "Copyright (C) 2012, Jonathan P Dawson" +__version__ = "0.1" + +import sys +import os + +from chips.compiler.compiler import comp + +if len(sys.argv) < 2 or "help" in sys.argv or "h" in sys.argv: + print "Usage: c2verilog.py [options] " + print + print "compile options:" + print " no_reuse : prevent register resuse" + print " no_concurrent : prevent concurrency" + print " no_initialize_memory : don't initialize memory" + print " speed : optimize for speed (defaults to area)" + print + print "tool options:" + print " iverilog : compiles using the icarus verilog compiler" + print " run : runs compiled code, used with ghdl or modelsimoptions" + sys.exit(-1) + +input_file = sys.argv[-1] +options = sys.argv[1:-1] +name, inputs, outputs, documentation = comp(input_file, options) + + +#run the compiled design using the simulator of your choice. +if "iverilog" in sys.argv: + import os + import tempfile + import shutil + verilog_file = os.path.abspath("%s.v"%name) + #tempdir = tempfile.mkdtemp() + #os.chdir(tempdir) + os.system("iverilog -o %s %s"%(name, verilog_file)) + if "run" in sys.argv: + result = os.system("vvp %s"%name) + if result: + sys.exit(1) + else: + sys.exit(0) + #shutil.rmtree(tempdir) + +#Add more tools here ...
chips2/c2verilog Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips2 =================================================================== --- chips2 (nonexistent) +++ chips2 (revision 2)
chips2 Property changes : Added: svbn:ignore ## -0,0 +1,3 ## +build +.gitignore +.git* Index: xilinx_input/xst_mixed.opt =================================================================== --- xilinx_input/xst_mixed.opt (nonexistent) +++ xilinx_input/xst_mixed.opt (revision 2) @@ -0,0 +1,45 @@ +FLOWTYPE = FPGA_SYNTHESIS; +######################################################### +## Filename: xst_mixed.opt +## +## Option File for XST targeted for speed +## For Mixed Language Designs (verilog/vhdl) +## This works for FPGA devices. +## +## Version: 13.1 +## $Header: /devl/xcs/repo/env/Jobs/Xflow/data/optionfiles/spartan6_xst_mixed_speed.opt,v 1.2 2011/01/05 01:18:16 rvklair Exp $ +######################################################### +# +# Options for XST +# +# +Program xst +-ifn _xst.scr; # input XST script file +-ofn _xst.log; # output XST log file +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +# +# The options listed under ParamFile are the XST Properties that can be set by the +# user. To turn on an option, uncomment by removing the '#' in front of the switch. +# +ParamFile: _xst.scr +"run"; +# +# Global Synthesis Options +# +"-ifn "; # Input/Project File Name +"-ifmt mixed"; # Input Format +"-ofn "; # Output File Name +"-ofmt ngc"; # Output File Format +"-top "; # Top Design Name +"-p "; # Target Device +"-opt_level 1"; # Optimization Effort Criteria + # 1 (Normal) or 2 (High) +"-opt_mode SPEED"; # Optimization Criteria + # AREA or SPEED +End ParamFile +End Program xst +# +# See XST USER Guide Chapter 8 (Command Line Mode) for all XST options +# + + Index: xilinx_input/ATLYS.prj =================================================================== --- xilinx_input/ATLYS.prj (nonexistent) +++ xilinx_input/ATLYS.prj (revision 2) @@ -0,0 +1,6 @@ +verilog work "user_design.v" +verilog work "server.v" +vhdl work "../source/serial_out.vhd" +vhdl work "../source/serial_in.vhd" +vhdl work "../source/gigabit_ethernet.vhd" +vhdl work "../source/atlys.vhd" Index: xilinx_input/ATLYS.ucf =================================================================== --- xilinx_input/ATLYS.ucf (nonexistent) +++ xilinx_input/ATLYS.ucf (revision 2) @@ -0,0 +1,79 @@ +NET "clk_in" LOC = "L15"; + +Net rst LOC=T15; +## System level constraints +Net rst TIG; + +## RS232 PORT +Net RS232_RX LOC=A16; +Net RS232_TX LOC=B16; + +## +NET "GPIO_BUTTONS<0>" LOC = "N4"; ## 2 on SW4 pushbutton (active-high) +NET "GPIO_BUTTONS<1>" LOC = "P4"; ## 2 on SW7 pushbutton (active-high) +NET "GPIO_BUTTONS<2>" LOC = "P3"; ## 2 on SW5 pushbutton (active-high) +NET "GPIO_BUTTONS<3>" LOC = "F6"; ## 2 on SW8 pushbutton (active-high) + +## +NET "GPIO_LEDS<0>" LOC = "U18"; +NET "GPIO_LEDS<1>" LOC = "M14"; +NET "GPIO_LEDS<2>" LOC = "N14"; +NET "GPIO_LEDS<3>" LOC = "L14"; +NET "GPIO_LEDS<4>" LOC = "M13"; +NET "GPIO_LEDS<5>" LOC = "D4"; +NET "GPIO_LEDS<6>" LOC = "P16"; +NET "GPIO_LEDS<7>" LOC = "N12"; + +## +NET "GPIO_SWITCHES<0>" LOC = "A10"; ## 1 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<1>" LOC = "D14"; ## 2 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<2>" LOC = "C14"; ## 3 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<3>" LOC = "P15"; ## 4 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<4>" LOC = "P12"; ## 4 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<5>" LOC = "R5"; ## 4 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<6>" LOC = "T5"; ## 4 on S2 DIP switch (active-high) +NET "GPIO_SWITCHES<7>" LOC = "E4"; ## 4 on S2 DIP switch (active-high) + +## +NET "PHY_RESET" LOC = "G13"; ## 36 ON U46 +NET "TXCLK" LOC = "K16"; ## 10 on U46 + +NET "TXD<0>" LOC = "H16"; ## 18 on U46 +NET "TXD<1>" LOC = "H13"; ## 19 on U46 +NET "TXD<2>" LOC = "K14"; ## 20 on U46 +NET "TXD<3>" LOC = "K13"; ## 24 on U46 +NET "TXD<4>" LOC = "J13"; ## 25 on U46 +NET "TXD<5>" LOC = "G14"; ## 26 on U46 +NET "TXD<6>" LOC = "H12"; ## 28 on U46 +NET "TXD<7>" LOC = "K12"; ## 29 on U46 + +NET "TXEN" LOC = "H15"; ## 16 on U46 +NET "TXER" LOC = "G18"; ## 13 on U46 +NET "GTXCLK" LOC = "L12"; ## 14 on U46 + +NET "RXD<0>" LOC = "G16"; ## 3 on U46 +NET "RXD<1>" LOC = "H14"; ## 128 on U46 +NET "RXD<2>" LOC = "E16"; ## 126 on U46 +NET "RXD<3>" LOC = "F15"; ## 125 on U46 +NET "RXD<4>" LOC = "F14"; ## 124 on U46 +NET "RXD<5>" LOC = "E18"; ## 123 on U46 +NET "RXD<6>" LOC = "D18"; ## 121 on U46 +NET "RXD<7>" LOC = "D17"; ## 120 on U46 + +NET "RXDV" LOC = "F17"; ## 4 on U46 +NET "RXER" LOC = "F18"; ## 8 on U46 +NET "RXCLK" LOC = "K15"; ## 7 ON U46 + +NET "CLK_IN" TNM_NET = "CLK_IN"; +TIMESPEC "TS_CLK" = PERIOD "CLK_IN" 10 ns HIGH 50% INPUT_JITTER 50.0ps; + +#Define the clock period of the 125MHz RXCLK +NET "RXCLK" TNM_NET = "RXCLK"; +TIMESPEC "TS_RXCLK" = PERIOD "RXCLK" 8000 ps HIGH 50 %; + +#Define the setup and hold times of RX data relative to RXCLK +INST "RXD" TNM = "IN_GMII"; +INST "RXDV" TNM = "IN_GMII"; +INST "RXER" TNM = "IN_GMII"; +TIMEGRP "IN_GMII" OFFSET = IN 2 ns VALID 2 ns BEFORE "RXCLK"; + Index: xilinx_input/bitgen.opt =================================================================== --- xilinx_input/bitgen.opt (nonexistent) +++ xilinx_input/bitgen.opt (revision 2) @@ -0,0 +1,23 @@ +FLOWTYPE = CONFIG; +############################################################### +## Filename: bitgen.opt +## +## Option File For Xilinx FPGA Bitgen Flow +## +## Version: 13.1 +## $Header: /devl/xcs/repo/env/Jobs/Xflow/data/optionfiles/bitgen.opt,v 1.14 2011/01/05 01:18:16 rvklair Exp $ +############################################################### +# +# Options for bitgen +# +# Type "bitgen -h " for a detailed list of command line options +# +Program bitgen +.ncd; # Input ncd file +-l; # Create logic allocation file +-w; # Overwrite existing output file +-m; # Create mask file +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +END Program bitgen + + Index: xilinx_input/balanced.opt =================================================================== --- xilinx_input/balanced.opt (nonexistent) +++ xilinx_input/balanced.opt (revision 2) @@ -0,0 +1,94 @@ +FLOWTYPE = FPGA; +############################################################### +## Filename: balanced.opt +## +## Option File For Xilinx FPGA Implementation Flow +## +## Version: 13.1 +## $Header: /devl/xcs/repo/env/Jobs/Xflow/data/optionfiles/fpga_balanced.opt,v 1.25 2011/01/05 01:18:16 rvklair Exp $ +############################################################### +# +# Options for Translator +# +# Type "ngdbuild -h" for a detailed list of ngdbuild command line options +# +Program ngdbuild +-p ; # Partname to use - picked from xflow commandline +-nt timestamp; # NGO File generation. Regenerate only when + # source netlist is newer than existing + # NGO file (default) +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +#-insert_keep_hierarchy; # Retain hierarchy identified by individual source input netlists +; # User design - pick from xflow command line +.ngd; # Name of NGD file. Filebase same as design filebase +End Program ngdbuild + +# +# Options for Mapper +# +# Type "map -h " for a detailed list of map command line options +# +Program map +-w; +-o _map.ncd; # Output Mapped ncd file +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +# -fp .mfp; # Floorplan file +# -gm incremental; # Guide mode +# -timing; # Perform Timing-Driven Packing and Placement +# -ol med; # Map Effort Levels. -ol [std|med|high] + # Note: If -timing is not specified, -ol switch is ignored. + # Device families supported: Virtex2, Virtex2P +.ngd; # Input NGD file +.pcf; # Physical constraints file +END Program map + +# +# Options for Post Map Trace +# +# Type "trce -h" for a detailed list of trce command line options +# +Program post_map_trce +-e 3; # Produce error report limited to 3 items per constraint +-xml _map.twx; # Output XML version of the timing report +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +#-o _map.twr; # Output trace report file +#-tsi _map.tsi; # Produce Timing Specification Interaction report +#-fastpaths; # Report minimum paths in verbose mode +#-nodatasheet; # Do not create the datasheet section of the report +_map.ncd; # Input mapped ncd +.pcf; # Physical constraints file +END Program post_map_trce + +# +# Options for Place and Route +# +# Type "par -h" for a detailed list of par command line options +# +Program par +-w; # Overwrite existing placed and routed ncd +-ol std; # Overall effort level +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +# -gm incremental; # Guide mode +_map.ncd; # Input mapped NCD file +.ncd; # Output placed and routed NCD +.pcf; # Input physical constraints file +END Program par + +# +# Options for Post Par Trace +# +# Type "trce -h" for a detailed list of trce command line options +# +Program post_par_trce +-e 3; # Produce error report limited to 3 items per constraint +-intstyle xflow; # Message Reporting Style: ise, xflow, or silent +-xml .twx; # Output XML version of the timing report +#-o .twr; # Output trace report file +#-tsi .tsi; # Produce Timing Specification Interaction report +#-fastpaths; # Report minimum paths in verbose mode +#-nodatasheet; # Do not create the datasheet section of the report +.ncd; # Input placed and routed ncd +.pcf; # Physical constraints file +END Program post_par_trce + + Index: configure_network =================================================================== --- configure_network (nonexistent) +++ configure_network (revision 2) @@ -0,0 +1 @@ +link scripts/configure_network \ No newline at end of file
configure_network Property changes : Added: svn:special ## -0,0 +1 ## +* \ No newline at end of property Index: ATLYS =================================================================== --- ATLYS (nonexistent) +++ ATLYS (revision 2)
ATLYS Property changes : Added: svn:ignore ## -0,0 +1 ## +*

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.