void CHtvDesign::SynHtDistRamWe(CHtvIdent *pHier, CHtvObject * pObj, CHtvObject * pRtnObj, CHtvOperand *pExpr, bool bIsAlwaysAt) { // Synthesize a write enable assignment statement // syntax is: variable = value // write variable as single bit wide value per dist ram section CHtvIdent *pWeIdent = pExpr->GetOperand1()->GetMember(); vector<CHtDistRamWeWidth> *pWeWidth = pWeIdent->GetHtDistRamWeWidth(); if ( (*pWeWidth).size() == 1) { if (!bIsAlwaysAt) m_vFile.Print("assign "); bool bFoundSubExpr; bool bWriteIndex; FindSubExpr(pObj, pRtnObj, pExpr, bFoundSubExpr, bWriteIndex); if (!bWriteIndex) { PrintSubExpr(pObj, pRtnObj, pExpr); m_vFile.Print(";\n"); } if (bFoundSubExpr) { m_vFile.DecIndentLevel(); m_vFile.Print("end\n"); } } else { int exprHighBit, exprLowBit; pExpr->GetOperand1()->GetDistRamWeWidth(exprHighBit, exprLowBit); CHtvIdent * pOp1Ident = pExpr->GetOperand1()->GetMember(); string origIdent = pOp1Ident->GetName(); for (size_t i = 0; i < (*pWeWidth).size(); i += 1) { int highBit = (*pWeWidth)[i].m_highBit; int lowBit = (*pWeWidth)[i].m_lowBit; if (!(exprLowBit < 0) && !(exprLowBit <= lowBit && highBit <= exprHighBit)) continue; string weName = VA("%s_%d_%d", origIdent.c_str(), highBit, lowBit); pOp1Ident->SetName(weName); if (!bIsAlwaysAt) m_vFile.Print("assign "); bool bFoundSubExpr; bool bWriteIndex; FindSubExpr(pObj, pRtnObj, pExpr, bFoundSubExpr, bWriteIndex); if (!bWriteIndex) { PrintSubExpr(pObj, pRtnObj, pExpr); m_vFile.Print(";\n"); } if (bFoundSubExpr) { m_vFile.DecIndentLevel(); m_vFile.Print("end\n"); } } pOp1Ident->SetName(origIdent); } }
void CHtvDesign::SynHtBlockQueRams(CHtvIdent *pHier) { string inputFileName = g_htvArgs.GetInputFileName(); CHtvIdentTblIter identIter(pHier->GetFlatIdentTbl()); for (identIter.Begin(); !identIter.End(); identIter++) { if (!identIter->IsVariable() || !identIter->IsHtBlockQue()) continue; CHtvIdent *pQueueRam = identIter(); m_bIs1CkHtBlockRamsPresent = true; // Block Ram int addrWidth = pQueueRam->GetType()->GetHtMemoryAddrWidth1(); addrWidth += pQueueRam->GetType()->GetHtMemoryAddrWidth2(); string cQueName = pQueueRam->GetName(); if (cQueName.substr(0,2) == "r_" || cQueName.substr(0,2) == "m_") cQueName.replace(0, 2, "c_"); else cQueName.insert(0, "c_"); string rQueName = pQueueRam->GetName(); if (rQueName.substr(0,2) == "m_") rQueName.replace(0, 2, "r_"); vector<int> refList(pQueueRam->GetDimenCnt(), 0); char buf[128]; do { string refDimStr; string modDimStr; for (size_t i = 0; i < refList.size(); i += 1) { sprintf(buf, "$%d", refList[i]); refDimStr += buf; sprintf(buf, "$%d", refList[i]); modDimStr += buf; } if (pQueueRam->GetType()->IsHtBlockRamDoReg()) m_vFile.Print("\n%s_HtBlockRam1CkDoReg #( .DATA_WIDTH(%d), .ADDR_WIDTH(%d) ) %s%s ( ", inputFileName.c_str(), pQueueRam->GetWidth(), addrWidth, pQueueRam->GetName().c_str(), modDimStr.c_str()); else m_vFile.Print("\n%s_HtBlockRam1Ck #( .DATA_WIDTH(%d), .ADDR_WIDTH(%d) ) %s%s ( ", inputFileName.c_str(), pQueueRam->GetWidth(), addrWidth, pQueueRam->GetName().c_str(), modDimStr.c_str()); bool bMultiple; CHtvIdent * pMethod = FindUniqueAccessMethod(&pQueueRam->GetHierIdent()->GetWriterList(), bMultiple); if (bMultiple) ParseMsg(PARSE_FATAL, pQueueRam->GetLineInfo(), "ht_queue push by muliple methods"); m_vFile.Print(".clk( %s ), ", pMethod->GetClockIdent()->GetName().c_str()); m_vFile.Print(".we( %s_WrEn%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".wa( %s_WrAddr%s[%d:0] ), ", rQueName.c_str(), refDimStr.c_str(), addrWidth-1); m_vFile.Print(".din( %s_WrData%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".ra( %s_RdAddr%s[%d:0] ), ", cQueName.c_str(), refDimStr.c_str(), addrWidth-1); m_vFile.Print(".dout( %s_RdData%s ) );\n", cQueName.c_str(), refDimStr.c_str()); } while (!pQueueRam->DimenIter(refList)); } }
void CHtvDesign::SynHtDistRams(CHtvIdent *pHier) { string inputFileName = g_htvArgs.GetInputFileName(); CHtvIdentTblIter identIter(pHier->GetFlatIdentTbl()); for (identIter.Begin(); !identIter.End(); identIter++) { if (!identIter->IsVariable() || !identIter->IsHtMemory()) continue; if (identIter->IsHtBlockRam() || identIter->IsHtMrdBlockRam() || identIter->IsHtMwrBlockRam() || identIter->IsHtQueue()) continue; CHtvIdent *pDistRam = identIter(); m_bIsHtDistRamsPresent = true; int addrWidth = pDistRam->GetType()->GetHtMemoryAddrWidth1(); addrWidth += pDistRam->GetType()->GetHtMemoryAddrWidth2(); vector<CHtDistRamWeWidth> *pWeWidth = pDistRam->GetHtDistRamWeWidth(); for (size_t j = 0; j < pWeWidth->size(); j += 1) { int highBit = (*pWeWidth)[j].m_highBit; int lowBit = (*pWeWidth)[j].m_lowBit; size_t i; for (i = 0; i < m_htDistRamTypes.size(); i += 1) { if (m_htDistRamTypes[i].m_addrWidth == addrWidth && m_htDistRamTypes[i].m_dataWidth == highBit-lowBit+1) break; } if (i == m_htDistRamTypes.size()) m_htDistRamTypes.push_back(CHtDistRamType(addrWidth, highBit-lowBit+1)); } string cQueName = pDistRam->GetName(); if (cQueName.substr(0,2) == "r_" || cQueName.substr(0,2) == "m_") cQueName.replace(0, 2, "c_"); else cQueName.insert(0, "c_"); bool bMultiple; CHtvIdent * pMethod = FindUniqueAccessMethod(&pDistRam->GetHierIdent()->GetWriterList(), bMultiple); if (bMultiple) ParseMsg(PARSE_FATAL, pDistRam->GetLineInfo(), "ht_queue push by muliple methods"); CHtvIdent *pClockIdent = pMethod->GetClockIdent(); vector<int> refList(pDistRam->GetDimenCnt(), 0); char buf[128]; do { string refDimStr; string modDimStr; for (size_t i = 0; i < refList.size(); i += 1) { sprintf(buf, "$%d", refList[i]); refDimStr += buf; sprintf(buf, "$%d", refList[i]); modDimStr += buf; } if (pWeWidth->size() == 1) { m_vFile.Print("\n%s_HtDistRam #( .DATA_WIDTH(%d), .ADDR_WIDTH(%d) ) %s%s ( ", inputFileName.c_str(), pDistRam->GetWidth(), addrWidth, pDistRam->GetName().c_str(), modDimStr.c_str()); m_vFile.Print(".clk( %s ), ", pClockIdent->GetName().c_str()); m_vFile.Print(".we( %s_WrEn%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".wa( %s_WrAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".din( %s_WrData%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".ra( %s_RdAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".dout( %s_RdData%s ) );\n", cQueName.c_str(), refDimStr.c_str()); } else { for (size_t j = 0; j < pWeWidth->size(); j += 1) { int highBit = (*pWeWidth)[j].m_highBit; int lowBit = (*pWeWidth)[j].m_lowBit; m_vFile.Print("\n%s_HtDistRam #( .DATA_WIDTH(%d), .ADDR_WIDTH(%d) ) %s%s_%d_%d ( ", inputFileName.c_str(), highBit-lowBit+1, addrWidth, pDistRam->GetName().c_str(), modDimStr.c_str(), highBit, lowBit); m_vFile.Print(".clk( %s ), ", pClockIdent->GetName().c_str()); m_vFile.Print(".we( %s_WrEn_%d_%d%s ), ", cQueName.c_str(), highBit, lowBit, refDimStr.c_str()); m_vFile.Print(".wa( %s_WrAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".din( %s_WrData%s[%d:%d] ), ", cQueName.c_str(), refDimStr.c_str(), highBit, lowBit); m_vFile.Print(".ra( %s_RdAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".dout( %s_RdData%s[%d:%d] ) );\n", cQueName.c_str(), refDimStr.c_str(), highBit, lowBit); } } } while (!pDistRam->DimenIter(refList)); } }
void CHtvDesign::SynHtAsymBlockRams(CHtvIdent *pHier) { string inputFileName = g_htvArgs.GetInputFileName(); CHtvIdentTblIter identIter(pHier->GetFlatIdentTbl()); for (identIter.Begin(); !identIter.End(); identIter++) { if (!identIter->IsVariable() || (!identIter->IsHtQueue() && !identIter->IsHtMemory())) continue; if (!identIter->IsHtMrdBlockRam() && !identIter->IsHtMwrBlockRam()) continue; CHtvIdent *pBlockRam = identIter(); // Block Ram int addrWidth = pBlockRam->GetType()->GetHtMemoryAddrWidth1(); addrWidth += pBlockRam->GetType()->GetHtMemoryAddrWidth2(); int selWidth = pBlockRam->GetType()->GetHtMemorySelWidth(); int dataWidth = pBlockRam->GetType()->GetType()->GetWidth(); string cQueName = pBlockRam->GetName(); if (cQueName.substr(0,2) == "r_" || cQueName.substr(0,2) == "m_") cQueName.replace(0, 2, "c_"); else cQueName.insert(0, "c_"); vector<int> refList(pBlockRam->GetDimenCnt(), 0); char buf[128]; do { string refDimStr; string modDimStr; for (size_t i = 0; i < refList.size(); i += 1) { sprintf(buf, "$%d", refList[i]); refDimStr += buf; sprintf(buf, "$%d", refList[i]); modDimStr += buf; } bool bMultiple; CHtvIdent * pWriteMethod = FindUniqueAccessMethod(&pBlockRam->GetHierIdent()->GetWriterList(), bMultiple); if (bMultiple) ParseMsg(PARSE_FATAL, pBlockRam->GetLineInfo(), "ht_asym_block_ram write by muliple methods"); CHtvIdent * pReadMethod = FindUniqueAccessMethod(&pBlockRam->GetHierIdent()->GetReaderList(), bMultiple); if (bMultiple) ParseMsg(PARSE_FATAL, pBlockRam->GetLineInfo(), "ht_asym_block_ram read by muliple methods"); if (pReadMethod->GetClockIdent()->GetName() == pWriteMethod->GetClockIdent()->GetName()) { if (pBlockRam->GetType()->IsHtBlockRamDoReg()) { if (identIter->IsHtMrdBlockRam()) { m_bIs1CkDoRegHtMrdBlockRamsPresent = true; m_vFile.Print("\n%s_HtBlockMrdRam1CkDoReg #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } if (identIter->IsHtMwrBlockRam()) { m_bIs1CkDoRegHtMwrBlockRamsPresent = true; m_vFile.Print("\n%s_HtBlockMwrRam1CkDoReg #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } } else { if (identIter->IsHtMrdBlockRam()) { m_bIs1CkHtMrdBlockRamsPresent = true; m_vFile.Print("\n%s_HtMrdBlockRam1Ck #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } if (identIter->IsHtMwrBlockRam()) { m_bIs1CkHtMwrBlockRamsPresent = true; m_vFile.Print("\n%s_HtMwrBlockRam1Ck #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } } m_vFile.Print(".ck( %s ), ", pWriteMethod->GetClockIdent()->GetName().c_str()); } else { if (pBlockRam->GetType()->IsHtBlockRamDoReg()) { if (identIter->IsHtMrdBlockRam()) { m_bIs2CkDoRegHtMrdBlockRamsPresent = true; m_vFile.Print("\n%s_HtMrdBlockRam2CkDoReg #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } if (identIter->IsHtMwrBlockRam()) { m_bIs2CkDoRegHtMwrBlockRamsPresent = true; m_vFile.Print("\n%s_HtMwrBlockRam2CkDoReg #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } } else { if (identIter->IsHtMrdBlockRam()) { m_bIs2CkHtMrdBlockRamsPresent = true; m_vFile.Print("\n%s_HtMrdBlockRam2Ck #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } if (identIter->IsHtMwrBlockRam()) { m_bIs2CkHtMwrBlockRamsPresent = true; m_vFile.Print("\n%s_HtMwrBlockRam2Ck #( .DATA_W(%d), .ADDR_W(%d), .SEL_W(%d) ) %s%s ( ", inputFileName.c_str(), dataWidth, addrWidth, selWidth, pBlockRam->GetName().c_str(), modDimStr.c_str()); } } m_vFile.Print(".rck( %s ), ", pReadMethod->GetClockIdent()->GetName().c_str()); m_vFile.Print(".wck( %s ), ", pWriteMethod->GetClockIdent()->GetName().c_str()); } m_vFile.Print(".we( %s_WrEn%s ), ", cQueName.c_str(), refDimStr.c_str()); if (identIter->IsHtMrdBlockRam()) m_vFile.Print(".ws( %s_WrSel%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".wa( %s_WrAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".wd( %s_WrData%s ), ", cQueName.c_str(), refDimStr.c_str()); if (identIter->IsHtMwrBlockRam()) m_vFile.Print(".rs( %s_RdSel%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".ra( %s_RdAddr%s ), ", cQueName.c_str(), refDimStr.c_str()); m_vFile.Print(".rd( %s_RdData%s ) );\n", cQueName.c_str(), refDimStr.c_str()); } while (!pBlockRam->DimenIter(refList)); } }
void CHtvDesign::SynHtDistRamWe(CHtvIdent *pHier, CHtvObject * pObj, CHtvObject * pRtnObj, CHtvOperand *pExpr, bool bIsAlwaysAt) { // Synthesize a write enable assignment statement // syntax is: variable = value // write variable as single bit wide value per dist ram section if (!bIsAlwaysAt) m_vFile.Print("assign "); vector<CHtfeOperand *> &weIndexList = pExpr->GetOperand1()->GetIndexList(); CHtvIdent *pWeIdent = pExpr->GetOperand1()->GetMember(); vector<CHtDistRamWeWidth> *pWeWidth = pWeIdent->GetHtDistRamWeWidth(); CHtvOperand *pOp2 = pExpr->GetOperand2(); Assert(pOp2->IsConstValue()); if ( (*pWeWidth).size() == 1) { bool bFoundSubExpr; bool bWriteIndex; FindSubExpr(pObj, pRtnObj, pExpr, bFoundSubExpr, bWriteIndex); if (!bWriteIndex) { PrintSubExpr(pObj, pRtnObj, pExpr); m_vFile.Print(";\n"); } if (bFoundSubExpr) { m_vFile.DecIndentLevel(); m_vFile.Print("end\n"); } } else { int exprHighBit, exprLowBit; pExpr->GetOperand1()->GetDistRamWeWidth(exprHighBit, exprLowBit); for (size_t i = 0; i < (*pWeWidth).size(); i += 1) { int highBit = (*pWeWidth)[i].m_highBit; int lowBit = (*pWeWidth)[i].m_lowBit; if (!(exprLowBit < 0) && !(exprLowBit <= lowBit && highBit <= exprHighBit)) continue; m_vFile.Print("%s_%d_%d", pWeIdent->GetName().c_str(), highBit, lowBit); for (size_t i = 0; i < weIndexList.size(); i += 1) { if (!weIndexList[i]->IsConstValue()) ParseMsg(PARSE_FATAL, weIndexList[i]->GetLineInfo(), "Non-constant index not supported"); m_vFile.Print("$%d", weIndexList[i]->GetConstValue().GetSint32()); } m_vFile.Print(" = "); if (pOp2->IsScX()) m_vFile.Print("1'bx;\n"); else if (pOp2->GetConstValue().GetUint64() == 0) m_vFile.Print("1'b0;\n"); else m_vFile.Print("1'b1;\n"); } } }