Commit 46a712c9 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

docs/specs/HDL: copy hdlspecs from old svn repo

parent fb415263
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
-- -*- Mode: LUA; tab-width: 2 -*-
PCR_template = reg {
name = "Port Control Register";
description = "Register controlling the mode of certain RTU port.";
prefix = "PCR";
field {
name = "Learning enable";
description = "1: enables learning process on this port. Unrecognized requests will be put into UFIFO\
0: disables learning. Unrecognized requests will be either broadcast or dropped.";
prefix = "LEARN_EN";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Pass all packets";
description = "1: all packets are passed (depending on the rules in RT table). \
0: all packets are dropped on this port.";
prefix = "PASS_ALL";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Pass BPDUs";
description = "1: BPDU packets (with dst MAC 01:80:c2:00:00:00) are passed according to RT rules. This setting overrides PASS_ALL.\
0: BPDU packets are passed according to RTU rules only if PASS_ALL is set.[ML by modified]";
prefix = "PASS_BPDU";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Fix priority";
description = "1: Port has fixed priority of value PRIO_VAL. It overrides the priority coming from the endpoint\
0: Use priority from the endpoint";
prefix = "FIX_PRIO";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Priority value";
description = "Fixed priority value for the port. Used instead the endpoint-assigned priority when FIX_PRIO = 1";
prefix = "PRIO_VAL";
type = SLV;
align = 4;
size =3 ;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Unrecognized request behaviour";
description = "Sets the port behaviour for all unrecognized requests:\
0: packet is dropped\
1: packet is broadcast";
prefix = "B_UNREC";
type = BIT;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
-- Mirroring Control fields go here.
};
peripheral {
name = "Routing Table Unit (RTU)";
prefix="rtu";
hdl_entity="wrsw_rtu_wb";
-- Port Configuration Register
reg {
name = "RTU Global Control Register";
description = "Control register containing global (port-independent) settings of the RTU.";
prefix = "GCR";
field {
name = "Main table bank select";
description = "Selects active bank of RTU hashtable (ZBT).\
0: bank 0 is used by lookup engine and bank 1 can be accessed using MFIFO\
1: bank 1 is used by lookup engine and bank 0 can be accessed using MFIFO";
type = BIT;
prefix = "HT_BSEL";
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Hash collision table (HCAM) bank select";
description = "Selects active bank of RTU extra memory for colliding hashes.\
0: bank 0 is used by lookup engine\
1: bank 1 is used by lookup engine";
type = BIT;
prefix = "HCAM_BSEL";
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "RTU Global Enable";
description = "Global RTU enable bit. Overrides all port settings.\
0: RTU is disabled. All packets are dropped.\
1: RTU is enabled.";
type = BIT;
prefix = "G_ENA";
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
field {
name = "Hash Poly";
description = "Determines the polynomial used for hash computation. Currently available: 0x1021, 0x8005, 0x0589 ";
type = SLV;
prefix = "POLY_VAL";
align = 8;
size = 16 ;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
clock = "zbt_clk_i";
};
-- TXTSU interrupts
irq {
name = "UFIFO Not Empty IRQ";
description = "Interrupt active when there are some requests in UFIFO.";
prefix = "nempty";
trigger = LEVEL_0;
};
fifo_reg {
name = "Unrecognized request FIFO (UFIFO)";
description = "FIFO containing all RTU requests for which matching entries haven't been found. CPU reads these requests,\
evaluates them and updates the RTU tables accordingly.";
prefix = "UFIFO";
direction = CORE_TO_BUS;
size = 128;
flags_dev = {FIFO_FULL, FIFO_EMPTY};
flags_bus = {FIFO_EMPTY, FIFO_COUNT};
--clock = "zbt_clk_i";
-- clock = ""; - make it asynchronous if you want
field {
name = "Destination MAC address least-significant part";
description = "Bits [31:0] of packet destination MAC address";
prefix = "DMAC_LO";
type = SLV;
size = 32;
};
field {
name = "Destination MAC address most-significant part";
description = "Bits [47:32] of packet destination MAC address";
prefix = "DMAC_HI";
type = SLV;
size = 16;
};
field {
name = "Source MAC address least-significant part";
description = "Bits [31:0] of packet source MAC address";
prefix = "SMAC_LO";
type = SLV;
size = 32;
};
field {
name = "Source MAC address most-significant part";
description = "Bits [47:32] of packet source MAC address";
prefix = "SMAC_HI";
type = SLV;
size = 16;
};
field {
name = "VLAN Identifier";
description = "VLAN ID of the packet (from the endpoint)";
prefix = "VID";
size = 12;
type = SLV;
align = 32;
};
field {
name = "Priority";
description = "Priority value (from the endpoint)";
prefix = "PRIO";
size = 3;
align = 4;
type = SLV;
};
field {
name = "Port ID";
description = "Identifier of RTU port to which came the request.";
prefix = "PID";
size = 4;
align = 4;
type = SLV;
};
field {
name = "VID valid";
description = "1: VID value is valid\
0: packet had no VLAN ID";
prefix = "HAS_VID";
align = 4;
type = BIT;
};
field {
name = "PRIO valid";
description = "1: PRIO value is valid\
0: packet had no priority assigned";
prefix = "HAS_PRIO";
type = BIT;
};
};
ram {
name = "Hash collisions memory (HCAM)";
description = "Memory block containing the 'tails' for hashes which have more than 4 entries and don't fit into a single bucket of main ZBT hashtable. \
<b>Note:</b> MSB of the address is the bank select bit. ";
prefix = "HCAM";
width = 32;
size = 32 * 8 * 2; -- 32 entries * 8 words per entry * 2 banks
access_dev = READ_ONLY;
access_bus = READ_WRITE;
clock = "zbt_clk_i"; --async?
};
ram {
name = "Aging bitmap for main hashtable";
description = "Each bit in this memory reflects the state of corresponding entry in main hashtable:\
0: entry wasn't matched\
1: entry was matched at least once.\
CPU reads this bitmap and subsequently clears it every few seconds to update the aging counters.";
prefix = "ARAM_MAIN";
width = 32;
size = 8192 / 32; -- 8192 bits
access_dev = READ_WRITE;
access_bus = READ_WRITE;
--[changed 6/10/2010] clock = "zbt_clk_i";
--clock = "zbt_clk_i"; --async?
};
ram {
name = "VLAN table (VLAN_TAB)";
description = "It stores VLAN-related information identified by VLAN ID (VID)";
prefix = "VLAN_TAB";
width = 32;
size = 4096 ; -- 4096 entries as defined in 802.1Q-2005, page 12
access_dev = READ_ONLY;
access_bus = READ_WRITE;
-- --[changed 6/10/2010] clock = "zbt_clk_i";
--clock = "zbt_clk_i"; --async?
};
reg {
name = "Aging register for HCAM";
description = "Each bit in this register reflects the state of corresponding entry in HCAM:\
0: entry wasn't matched\
1: entry was matched at least once.\
CPU reads this bitmap and subsequently clears it every few seconds to update the aging counters.";
prefix = "AGR_HCAM";
field {
name = "Aging register value";
type = SLV;
size = 32;
access_dev = READ_WRITE;
access_bus = READ_WRITE;
load = LOAD_EXT;
};
clock = "zbt_clk_i";
-- clock = "zbt_clk_i"; --async?
};
fifo_reg {
name = "Main hashtable CPU access FIFO (MFIFO)";
description = "FIFO for writing to main hashtable";
prefix = "MFIFO";
direction = BUS_TO_CORE;
size = 64;
flags_dev = {FIFO_EMPTY, FIFO_COUNT};
flags_bus = {FIFO_EMPTY, FIFO_FULL, FIFO_COUNT};
field {
name = "Address/data select";
description = "1: AD_VAL contains new memory address\
0: AD_VAL contains data word to be written at current memory address. Then, the address is incremented";
prefix = "AD_SEL";
type = BIT;
};
field {
name = "Address/data value";
description = "Value of new memory address (when AD_SEL = 1) or data word to be written (when AD_SEL = 0)";
prefix = "AD_VAL";
type = SLV;
align =32;
size = 32;
};
clock = "zbt_clk_i";
};
};
function gen_PCRs(num_pcrs)
local i;
for i=0,num_pcrs-1 do
local rp = deepcopy(PCR_template);
rp.name = rp.name.." "..i;
rp.prefix = rp.prefix..i;
table.insert(periph, rp);
end
end
gen_PCRs(10);
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
-------------------------------------------------------------------------------
-- Title : SWcore pseudocode
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : wrsw_hdl_spec.txt
-- Authors : Maciej Lipinski (maciej.lipinski@cern.ch)
-- Company : CERN BE-CO-HT
-- Created : 2012-01-11
-- Last update: 2012-01-211
-- Description: this is kind-of-pseudo code which attempts to explain how the
-- SWcore and its output queues are working.
-- It does not meant to compile.
-------------------------------------------------------------------------------
*/
#define OUT_QUEUE_NUMBER 8;
#define PORT_NUMBER 8; //whatever
#define FBM_MEMORY_SIZE 123456; //whatever
typedef struct {
FIFO single_prio_fifo; // this is an abstract type of First In First Out
boolean empty; // true if the FIFO is empty
} swcore_out_quque_t;
typedef struct {
ETHERNET_FRAME buf; // here the frame is stored
} swcore_FBM_entry_t;
typedef struct {
boolean valid; // true if the rest of the data is valid
int address; // address of the first page of the frame in the memory
int port_mask;// to which ports the frame is to be forwarded (e.g.: 0101 => forward to
// ports: 0 and 2,
int priority; // with what priority
} swcore_transfer_t;
// here we declare output queues for all the ports and their priorities
swcore_out_quque_t output[PORT_NUMBER][OUT_QUEUE_NUMBER];
// the Fabulously Big Memory (FBM)
swcore_FBM_entry_t fbm_memory[FBM_MEMORY_SIZE];
//this is used to transfer frame from input ports to output ports
swcore_transfer_t transfer[PORT_NUMBER];
boolean receive(ETHERNET_FRAME *buf, int port_number)
{
/*
* this function receives Ethernet frames from the physical interface of the port_number
*/
}
boolean send(ETHERNET_FRAME *buf, int port_number)
{
/*
* this function sends Ethernet frames to the physical interface of the port_number
*/
}
boolean rtu(ETHERNET_FRAME *buf, int *port_mask, int *priority)
{
/*
* here, the routing decision is taken
* the output of this function are:
* - the decision to which ports the frame should go (port_mask)
* - the decision what is the priority of the frame
* - (in the future) it will also tell whether it is broadcast or unicast
*/
}
int mmu()
{
/*
* Memory Management Unit - returns the address of the page allocated in the FBM memory
*/
}
/*
this function takes data from an ports' input and makes it available to ports' output
*/
void arbiter(int port_mask,int priority,int address, int port_number /*input*/)
{
transfer[port_number].address = address;
transfer[port_number].port_mask = port_mask;
transfer[port_number].priority = priority;
transfer[port_number].valid = TRUE;
// here we wait for all the appropriate ports' outputs to read the data
while (transfer[port_number].port_mask != 0);
transfer[port_number].valid = FALSE;
}
/*
input block, this is per port
*/
void input_block(int port_number)
{
ETHERNET_FRAME buf; //an abstract type to store a received Ethernet frame
int port_mask;
int priority;
int address;
while(1)
{
if( receive(&buf,port_number) == TRUE )
{
// ask Routing Table Unit
rtu(&buf, &port_mask, &priority);
//acquire address of the first page
address = mmu();
//store in memory
fbm_memory[address].buf = buf;
// forward a pointer to the frame to all the appropriate ports
// waits until all the appropriate ports read the data
arbiter(port_mask, priority, address);
}
}
}
void output_block(int port_number)
{
int address;
/* the below two whiles are done simultaneously (try to imagine :)*/
while(1)
{
for(int i=0; i<PORT_NUMBER; i++)
{
if( (transfer[i].port_mask >> port_number) & 0x1 ) // we check all the input ports for a frame
{ // destined to the port
int addresss = transfer[i].address;
int priority = transfer[i].priority;
// put the address of the first page of the frame into the output fifo for a given priority
output[port_number][priority].single_prio_fifo.push(address);
output[port_number][priority].empty = FALSE;
// indicate that the frame was received by the output port
transfer[i].port_mask = transfer[i].port_mask & (0x1 << port_number);
}
}
}
// here is the very "advanced" output scheduling algorithm
while(1)
{
for(int i=OUT_QUEUE_NUMBER-1; i>=0; i--)
{
if( output[port_number][i].empty == FALSE)
{
// get the pointer to the oldest frame in the output queue
address = output[port_number][i].single_prio_fifo.front();
// send the frame
send(fbm_memory[address], port_number);
}
}
}
}
void swcore_main()
{
int port_number;
/*
* if you imagine that all the below functions are executed simultaneusly,
* then you have the idea how the SWCORE works
*/
// PORT_NUMBER input ports
input_block(0);
input_block(1);
input_block(2);
input_block(3);
input_block(4);
input_block(5);
input_block(6);
input_block(7);
// PORT_NUMBER of output ports
input_block(0);
input_block(1);
input_block(2);
input_block(3);
input_block(4);
input_block(5);
input_block(6);
input_block(7);
}
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment