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::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::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"); } } }